2018南京大学计算机夏令营机试第二题(回溯)

  1. Missing number

Given a positive integer n(n≤40), pick n-1 numbers randomly from 1 to n and concatenate them in random order as a string s, which means there is a missing number between 1 and n. Can you find the missing number?(Notice that in some cases the answer will not be unique, and in these cases you only need to find one valid answer.)
input:
20
81971112205101569183132414117
output
16

中文题意:给定正整数n(n≤40),从1到n中随机选择n-1个数,并将它们以随机顺序连接为字符串s,这意味着在1和n之间有一个缺失的数字。你能找到那个缺失的数字吗?(请注意在某些情况下答案不唯一,此时你只需要找到一个有效的答案。)

因为n的值比较小,采用回溯法,当递归到某个字符时,考虑两种情况:
①该字符是一个小于10的整数,若合法则进行下一次递归,修改idx+1
②该字符与下一个字符组成一个二位整数,且合法,则进行下一次递归,修改idx+2。
注意两个条件是并列情况,即①不满足的时候还是可以执行②。

代码:

#include 
#include 
#include
#include
using namespace std;

int vis[45];
int n;
string s;
int flag = 0;

void dfs(string &s, int idx) {
	if (flag)  //找到一个可行解后就返回,避免输出多个答案
		return;
	if (idx == s.length()) {//返回正确答案
		flag = 1;
		for (int i = 1; i <= n; i++)
			if (!vis[i])
				cout << i;
		return;
	}
	//当前1个数字
	if (s[idx] == '0')//一位和两位整数都不可能出现为0的情况
		return;
	if (s[idx] - '0' <= n && !vis[s[idx] - '0']) {
		vis[s[idx] - '0'] = 1; //访问
		dfs(s, idx + 1);
		vis[s[idx] - '0'] = 0; //恢复标志位
	}
	//当前两个数字
	if (idx < s.length() - 1) { //使得idx + 1合法
		int num = (s[idx] - '0') * 10 + s[idx + 1]-'0';
		if (num <= n && !vis[num]) {
			vis[num] = 1;
			dfs(s, idx + 2);
			vis[num] = 0;
		}
	}
}


int main()
{
	cin >> n;
	cin >> s;
	dfs(s, 0);
	return 0;
	
}

你可能感兴趣的:(DFS例题)