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 }
posted @ 2014-07-19 15:04  Naturain  阅读(334)  评论(0编辑  收藏  举报