Uva--185(回溯,剪枝)
2014-07-19 14:52:09
题意&思路:(1)先把罗马数字转化为阿拉伯数字,判断等式是否成立以确定是 Correct 还是 Incorrect。
具体转化方法借鉴了别人:定义两个pointer:i,j,从罗马数字(字符串)的末尾开始扫,以罗马数字末尾的数字为初始值,i 初始在末尾,j 初始在 i 的相邻左边。
如果 j 所示的数值比 i 所示的数值小(比如X比C小),那么值减去 j 所示的数值,j 左移;
如果 j 所示的数值 >= i 所示数值,那么值加上 j 所示数值,i 到 j 的位置,j左移。就这样循环到头部,所得的值就是对应阿拉伯数字。
(2)开始从第一个字母开始枚举(注意如果该字母是第一个字母,则不能赋为0)
每放一个数,就把和这个位置有相同字母且没有被放过的位置放相同的数字。(这算一个剪枝,因为再搜索到这些位置就不用考虑其他数了)
1 /************************************************************************* 2 > File Name: Uva185.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sat 19 Jul 2014 12:05:41 PM CST 6 ************************************************************************/ 7 8 #include<iostream> 9 #include<cmath> 10 #include<algorithm> 11 #include<cstring> 12 #include<cstdio> 13 #include<fstream> 14 using namespace std; 15 16 int al[150],Judge2; 17 int a,b,c,stlen,Judge1,li[100],used[10]; 18 char str[100],s[3][15]; 19 20 int Change(char *s){ 21 int len = strlen(s); 22 int i = len - 1,j = len - 2,sum = al[s[len - 1]]; 23 while(j >= 0){ 24 if(al[s[j]] < al[s[i]]){ 25 sum -= al[s[j]]; 26 --j; 27 } 28 else{ 29 sum += al[s[j]]; 30 i = j; 31 --j; 32 } 33 } 34 return sum; 35 } 36 37 bool Check(){ 38 int number[3] = {0,0,0},flag = 0; 39 for(int i = 0; i < stlen; ++i){ 40 if(li[i] == -1) 41 ++flag; 42 else 43 number[flag] = number[flag] * 10 + li[i]; 44 } 45 //printf("preJudge2 : %d %d+%d =? %d\n",Judge2,number[0],number[1],number[2]); 46 if(number[0] + number[1] == number[2]) 47 return true; 48 return false; 49 } 50 51 void Dfs(int cur){ 52 if(cur >= stlen){ 53 if(Check()) 54 ++Judge2; 55 return; 56 } 57 if(li[cur] == -1 && str[cur] != '+' && str[cur] != '='){ 58 int st; 59 if(cur == 0) st = 1; 60 else st = 0; 61 for(int i = st; i <= 9; ++i){ 62 //li[cur]放i 63 if(used[i]) continue; 64 for(int j = 0; j < stlen; ++j) 65 if(str[cur] == str[j]) 66 li[j] = i; 67 used[i] = 1; 68 Dfs(cur + 1); 69 used[i] = 0; 70 for(int j = 0; j < stlen; ++j) 71 if(str[cur] == str[j]) 72 li[j] = -1; 73 } 74 } 75 else Dfs(cur + 1); 76 } 77 78 int main(){ 79 al['I'] = 1; 80 al['V'] = 5; 81 al['X'] = 10; 82 al['L'] = 50; 83 al['C'] = 100; 84 al['D'] = 500; 85 al['M'] = 1000; 86 while(scanf("%s",str) == 1){ 87 if(str[0] == '#') 88 break; 89 stlen = strlen(str); 90 int tag = 0,cnt = 0,flag = 0; 91 for(int i = 0; i < stlen; ++i){ 92 if(str[i] == '+' || str[i] == '=' || i == stlen - 1){ 93 if(i == stlen - 1) 94 s[tag][cnt++] = str[i]; 95 s[tag][cnt] = '\0'; 96 ++tag; 97 cnt = 0; 98 } 99 else 100 s[tag][cnt++] = str[i]; 101 } 102 a = Change(s[0]); 103 b = Change(s[1]); 104 c = Change(s[2]); 105 Judge1 = 0; 106 if(a + b == c) 107 Judge1 = 1; 108 //printf("%d %d %d\n",a,b,c); 109 Judge2 = 0; 110 for(int i = 0; i < stlen; ++i) li[i] = -1; 111 memset(used,0,sizeof(used)); 112 Dfs(0); 113 if(Judge1) printf("Correct "); 114 else printf("Incorrect "); 115 116 if(Judge2 == 0) printf("impossible\n"); 117 else if(Judge2 == 1) printf("valid\n"); 118 else printf("ambiguous\n"); 119 } 120 return 0; 121 }