1. 程式人生 > >「美團 CodeM 資格賽」跳格子

「美團 CodeM 資格賽」跳格子

exit bug fine 提示 我們 oid sizeof lan ems

題目描述

nnn 個格子排成一列,一開始,你在第一個格子,目標為跳到第 n 個格子。在每個格子 i 裏面你可以做出兩個選擇:

  • 選擇「a」:向前跳 ai?? 步。
  • 選擇「b」:向前跳 bi 步。

把每步的選擇寫成一個關於字符 ab的字符串。求到達格子 n 的方案中,字典序最小的字符串。當做出某個選擇時,你跳出了這n個格子的範圍,則這個選擇是不合法的。

  • 當沒有合法的選擇序列時,輸出 No solution!
  • 當字典序最小的字符串無限長時,輸出 Infinity!
  • 否則,輸出這個選擇字符串。

輸入格式

輸入有三行。


第一行輸入一個整數 n
第二行輸入 n 個整數,分別表示 ai??。
第三行輸入 n 個整數,分別表示 bi

輸出格式

輸出一行字符串表示答案。

樣例

樣例輸入

7
5 -3 6 5 -5 -1 6
-6 1 4 -2 0 -2 0

樣例輸出

abbbb

數據範圍與提示

1≤n≤105

−n≤ai,bi≤n

Solution:

  本題主要是貪心加搜索。由於題目中需要輸出字典序最小的字符串,所以我們貪心盡可能的走a是肯定沒有問題的。於是我們從前往後dfs,盡可能的走a,判斷走a後的點能否到達n點,若能到達就標記,當然到達n後就跳出dfs,dfs完後判斷n點是否被標記,沒被標記就無解,被標記了就再來一次dfs記錄路徑,同時標記點是否被訪問,若一個點被訪問兩次則說明有環,輸出Infinity。否則就輸出記錄的字符串。

代碼:

#include<bits/stdc++.h>
#define il inline
#define ll long long 
#define debug pritnf("%d %s\n",__LINE__,__FUNCTION__)
using namespace std;
const int N=100005;
il int gi()
{
    int a=0;char x=getchar();bool f=0;
    while((x<0||x>9)&&x!=-)x=getchar();
    if(x==
-)x=getchar(),f=1; while(x>=0&&x<=9)a=a*10+x-48,x=getchar(); return f?-a:a; } int n,tot,net[N][2]; char s[N]; bool vis[N],pd[N]; il void dfs(int x) { vis[x]=1; if(x==n){pd[x]=1;return;} for(int i=0;i<=1;i++){ int nx=x+net[x][i]; if(1<=nx&&nx<=n){ if(!vis[nx])dfs(nx); if(pd[nx])pd[x]=1; } } } il void killans(int x) { if(x==n){ for(int i=1;i<=tot;i++)printf("%c",s[i]); exit(0); } if(vis[x]){printf("Infinity!");exit(0);} for(int i=0;i<=1;i++) { int nx=x+net[x][i]; if(1<=nx&&nx<=n){ if(pd[nx])s[++tot]=i+a,killans(nx); } } } int main() { n=gi(); for(int i=1;i<=n;i++)net[i][0]=gi(); for(int i=1;i<=n;i++)net[i][1]=gi(); dfs(1); if(!pd[1]){printf("No solution!");return 0;} memset(vis,0,sizeof(vis)); killans(1); return 0; }

「美團 CodeM 資格賽」跳格子