哎呀,好久没更新了,今天来一篇吧!
UVa12107数字谜
题意:
给出数字谜,要求修改尽量少的数,使得修改后的数字谜有唯一的解。
修改指的是随意替换,空格与数字、数字与数字都可以互相替换,但涉及的数必须是没有前导零的正数,输出是修改后的数字谜。
(建议看英文原题,这道题的英文原题比较好读懂)
思路:
通过观察,发现求出尽量少的数,所以采用迭代加深搜索,而且数字谜的大小并不大,所以暴力枚举能过,
由于要求出唯一的解,所以我们应该先迭代加深搜索数字谜,然后再dfs解出来,这样就行了,我想估计我的想法不够
简单,所以时间为2650ms,不过能够过。
下面是代码:
// UVa 12107 // IDA* + 剪枝 #include <cstdio> #include <cstring> using namespace std; const char alpha[] = { '*', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; int c1, c2, c3, cnt, maxd; char str[20], ans[20]; bool Vis() { if (str[0] == '0' || str[c1] == '0' || str[c2] == '0') return false; if (str[c1-1] != '*' && str[c2-1] != '*' && str[c3-1] != '*') { int a = str[c1-1] - '0', b = str[c2-1] - '0', c = str[c3-1] - '0'; return (a*b) % 10 == c; } return true; } bool Vis1() { int a = 0, b = 0, c = 0; for (int i = 0; i < c1; ++i) a = a * 10 + str[i] - '0'; for (int i = c1; i < c2; ++i) b = b * 10 + str[i] - '0'; for (int i = c2; i < c3; ++i) c = c * 10 + str[i] - '0'; return a * b == c; } void dfs1(int from) { int i; for (i = from; i < strlen(str); ++i) if (str[i] == '*') break; if (i == c3) { if (Vis1()) ++cnt; return; } for (int j = 1; j < 11; ++j) { char rem[20]; memcpy(rem, str, sizeof(rem)); str[i] = alpha[j]; if (Vis()) dfs1(i+1); if (cnt > 1) return; memcpy(str, rem, sizeof(rem)); } } bool better() { for (int i = 0; i < c3; ++i) if (str[i] != ans[i]) { return ans[i] == ' ' || str[i] < ans[i]; } return false; } bool dfs(int d, int from) { if (d == maxd) { cnt = 0; memcpy(ans, str, sizeof(ans)); if (Vis()) dfs1(0); return cnt == 1; } if (from == c3) return false; for (int j = 0; j < 11; ++j) { char rem[20]; if (str[from] == alpha[j]) { memcpy(rem, str, sizeof(rem)); if (dfs(d, from+1)) return true; memcpy(str, rem, sizeof(rem)); } if (str[from] != alpha[j]) { memcpy(rem, str, sizeof(rem)); str[from] = alpha[j]; if (dfs(d+1, from+1)) return true; memcpy(str, rem, sizeof(rem)); } } return false; } int main() { int kase = 0; char a[10], b[10], c[10]; while (scanf("%s", a) == 1 && a[0] != '0') { scanf("%s%s", b, c); c1 = strlen(a), c2 = strlen(a) + strlen(b), c3 = strlen(a) + strlen(b) + strlen(c); memcpy(str, a, sizeof(a)); strcat(str, b), strcat(str, c); for (int i = 0; i < c3; ++i) ans[i] = ' '; char rem[20]; memcpy(rem, str, sizeof(rem)); for (maxd = 0; ; ++maxd) { Set.clear(); if (dfs(0, 0)) break; memcpy(str, rem, sizeof(str)); } printf("Case %d: ", ++kase); for (int i = 0; i < c1; ++i) printf("%c", ans[i]); printf(" "); for (int i = c1; i < c2; ++i) printf("%c", ans[i]); printf(" "); for (int i = c2; i < c3; ++i) printf("%c", ans[i]); printf(" "); } return 0; }
看了看时间并不是很占优势,所以接下来我会再发布一篇博客,所以说120ms左右的代码。