LOJ#6084. 「美团 CodeM 资格赛」跳格子

版权声明:转载请注明 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;
}

猜你喜欢

转载自blog.csdn.net/qq_33831360/article/details/88605908
今日推荐