「美團 CodeM 資格賽」跳格子
阿新 • • 發佈:2018-02-07
exit bug fine 提示 我們 oid sizeof lan ems
第一行輸入一個整數 n。
第二行輸入 n 個整數,分別表示 ai??。
第三行輸入 n 個整數,分別表示 bi。
題目描述
nnn 個格子排成一列,一開始,你在第一個格子,目標為跳到第 n 個格子。在每個格子 i 裏面你可以做出兩個選擇:
- 選擇「a」:向前跳 ai?? 步。
- 選擇「b」:向前跳 bi 步。
把每步的選擇寫成一個關於字符 a
和 b
的字符串。求到達格子 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 資格賽」跳格子