题目链接:
https://vjudge.net/problem/UVA-12107
题意:
给出一个数字谜,要求修改尽量少的数,使修改后的数字谜只有唯一解。空格和数字可以随意替换,但不能增删,数字谜中所有涉及的数必须是没有前导零的正数。输入数字谜一定形如a*b=c,其中a、b、c分别最多有2、2、4位。
题解:
http://www.cnblogs.com/tyty-Somnuspoppy/p/6366725.html
1、因为输出字典序最小,所以每一位数按“*0123456789”顺序枚举。
2、如果当前要修改的数与即将被修改的数相同,则cnt不加1。
3、检查积的时候,为防超时,只枚举两个乘数,通过检查积的位数和积的已确定数字来验证。
4、遇到空格要跳过并检查返回结果。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 1e5+10; 17 18 string s,ss = "*0123456789"; 19 pair<int,int> mp[3]; 20 int maxd,num,len; 21 22 bool leadingzero(int x){ 23 for(int i=0; i<2; i++) 24 if(mp[i].first == x) return true; 25 return false; 26 } 27 28 int changetodigit(string str){ 29 int res = 0; 30 for(int i=0; i<(int)str.size(); i++) 31 res = res*10 + str[i]-'0'; 32 return res; 33 } 34 35 bool check(){ 36 int x = changetodigit(s.substr(mp[0].first,mp[0].second-mp[0].first+1)); 37 int y = changetodigit(s.substr(mp[1].first,mp[1].second-mp[1].first+1)); 38 char str[5]; 39 sprintf(str,"%d",x*y); 40 int len = strlen(str); 41 if(mp[2].second-mp[2].first+1 != len) return false; 42 for(int i=mp[2].first; i<=mp[2].second; i++){ 43 if(s[i] == '*') continue; 44 if(s[i] != str[i-mp[2].first]) return false; 45 } 46 return true; 47 } 48 49 void judge(int cur){ 50 if(num>1) return ; 51 if(cur == mp[1].second+1){ 52 if(check()) ++num; // 通过前两个数字相乘 判断有没有可能等于第三个数 53 return ; 54 } 55 if(s[cur] != '*') judge(cur+1); 56 else{ 57 for(int i=1; i<11; i++){ // 枚举前两个数字 ’*‘ 的位置 的全部可能 58 if(i==1 && leadingzero(cur)) continue; 59 s[cur] = ss[i]; 60 judge(cur+1); 61 s[cur] = '*'; 62 } 63 } 64 } 65 66 67 bool dfs(int d,int cur){ 68 if(d >= maxd){ 69 string tmp = s; 70 num = 0; 71 judge(0); // 给出一种数字谜,判断这种的是不是唯一解 72 if(num == 1) return true; 73 s = tmp; 74 return false; 75 } 76 77 if(cur == len) return false; 78 if(s[cur] == ' '){ 79 if(dfs(d,cur+1)) return true; 80 }else{ 81 char c = s[cur]; 82 for(int i=0; i<11; i++){ 83 if(i==1 && leadingzero(cur)) continue; 84 if(c == ss[i]) { 85 if(dfs(d,cur+1)) return true; 86 }else{ 87 s[cur] = ss[i]; 88 if(dfs(d+1,cur+1)) return true; 89 s[cur] = c; 90 } 91 } 92 } 93 return false; 94 95 } 96 97 int main(){ 98 int cas = 0; 99 while(getline(cin,s)){ 100 if(s[0] == '0') break; 101 len = s.size(); 102 int cnt=0,start=0; 103 for(int i=0; i<len; i++){ 104 if(s[i] == ' '){ 105 mp[cnt++] = make_pair(start,i-1); 106 start = i+1; 107 } 108 } 109 mp[cnt] = make_pair(start,len-1); 110 111 printf("Case %d: ",++cas); 112 for(maxd=0; ; maxd++){ // IDA*迭代加深搜索, 枚举上限,最多修改的次数 113 if(dfs(0,0)){ 114 printf("%s ",s.c_str()); 115 break; 116 } 117 } 118 } 119 120 return 0; 121 }