【Gym - 101889E Enigma 】【暴力dfs+记忆化】【补充最小的数使得被n整除】

【链接】:

https://odzkskevi.qnssl.com/fa6682426fb11e87a5ab9246f22a461d?v=1535768440

【题意】:

给你一个包含数字和问号的字符串,在问好处填数字,使得最小的数能被n整除

|s|<=1e3,n<=1e3

【思路】:

暴力dfs+记忆化,每个点状态:[现在的位数][现在的模数],1000*1000的状态记忆化一下,每次只会遍历到一次。

【代码】:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 6;
char s[maxn];
string ans;
int vis[maxn][maxn], flag[maxn][maxn];
int n;
int len;

int dfs(int now, int mod) {
	if (now == len)return mod == 0;
	if (vis[now][mod] != -1)return flag[now][mod];
	vis[now][mod] = 1;
	int &ret = flag[now][mod];
	if (s[now] == '?') {
		for (int i = !now; i <= 9; i++) {
			ret |= dfs(now + 1, (mod * 10 + i) % n);
			if (ret)return 1;
		}
		return 0;
	}
	else {
		ret |= dfs(now + 1, (mod * 10 + s[now] - '0') % n);
		return ret;
	}
}

void f(int now, int mod) {
	if (now == len) return;
	if (s[now] == '?') {
		for (int i = !now; i < 10; i++) {
			if (dfs(now + 1, (mod * 10 + i) % n)) {
				ans += '0' + i;
				f(now + 1, (mod * 10 + i) % n);
				return;
			}
		}
	}
	else {
		ans += s[now];
		f(now + 1, (mod * 10 + s[now] - '0') % n);
		return;
	}
}

int main() {
	scanf("%s", s);
	scanf("%d", &n);
	len = strlen(s);
	memset(vis, -1, sizeof(vis));
	memset(flag, 0, sizeof(flag));
	if (dfs(0, 0)) {
		f(0, 0);
		cout << ans << endl;
	}
	else printf("*\n");
}

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/82319138