版权声明:转载请注明 https://blog.csdn.net/qq_33831360/article/details/88605908
题目描述
nn 个格子排成一列,一开始,你在第一个格子,目标为跳到第 nn 个格子。在每个格子 ii 里面你可以做出两个选择:
- 选择「a」:向前跳 a_iai 步。
- 选择「b」:向前跳 b_ibi 步。
把每步的选择写成一个关于字符
a
和b
的字符串。求到达格子 nn 的方案中,字典序最小的字符串。当做出某个选择时,你跳出了这n个格子的范围,则这个选择是不合法的。
- 当没有合法的选择序列时,输出
No solution!
。- 当字典序最小的字符串无限长时,输出
Infinity!
。- 否则,输出这个选择字符串。
输入格式
输入有三行。
第一行输入一个整数 nn。
第二行输入 nn 个整数,分别表示 a_iai。
第三行输入 nn 个整数,分别表示 b_ibi。输出格式
输出一行字符串表示答案。
其实不用想复杂
先写一个普通的搜索与回溯找一条路径,对于每个点能选a就选a,不能就选b
找不到则无解
找到后考虑Infinity的情况,其实等价于在某点处选b以后有路径到终点,选a会回到以前来过的点,形成环,以后会在环里转无数次后选b到终点,路径是无限长的。
#include <iostream>
#include <cstdio>
using namespace std;
int a[100004],b[100005],n;
int st[100004],tp,v[100005];
void dfs(int k) {
if (k <= 0 || k > n) return;
if (v[k]) return;
v[k] = 1;
if(k == n) {
for (int i = 1; i <= n; i++) v[i] = 0;
int pos = 1; v[1] = 1;
for (int i = 1; i <= tp; i++) {
if (st[i] == 0) pos += a[pos];
else {
if (pos+a[pos]>0 && pos+a[pos]<=n && v[pos+a[pos]]) {
puts("Infinity!");
exit(0);
}
pos += b[pos];
}
v[pos] = 1;
}
for (int i = 1; i <= tp; i++) printf("%c",st[i]?'b':'a');
exit(0);
}
st[++tp] = 0;
dfs(k+a[k]);
tp--;
st[++tp] = 1;
dfs(k+b[k]);
tp--;
}
int main() {
cin >> n;
for (int i = 1 ;i <= n; i++) scanf("%d",&a[i]);
for (int i = 1; i <= n; i++) scanf("%d",&b[i]);
dfs(1);
printf("No solution!");
return 0;
}