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 }

转载于:https://www.cnblogs.com/naturepengchen/articles/3854984.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
0-1背包问题是一个经典的组合优化问题,目标是在给定的一组物品中选择一些物品放入背包,使得物品的总重量不超过背包的容量,同时总价值最大化。回溯法是一种解决0-1背包问题的方法。 回溯法的基本思想是通过递归的方式,穷举所有可能的解,并通过剪枝操作来减少不必要的计算。具体步骤如下: 1. 定义一个递归函数backtrack,该函数接受四个参数:当前物品的索引i,当前背包的重量cw,当前背包的价值cv,以及剩余物品的重量和价值数组。 2. 在backtrack函数中,首先判断递归终止条件。如果当前物品的索引i等于物品个数n,或者当前背包的重量cw大于背包容量c,则返回当前背包的价值cv。 3. 如果递归没有终止,那么有两种情况需要考虑: - 选择当前物品放入背包:将当前物品的重量和价值加到cw和cv上,并递归调用backtrack函数,更新当前物品的索引i为i+1。 - 不选择当前物品放入背包:直接递归调用backtrack函数,更新当前物品的索引i为i+1。 4. 在每次递归调用后,比较选择和不选择两种情况的结果,返回价值较大的那个。 5. 最后,调用backtrack函数,传入初始参数i=0,cw=0,cv=0,得到0-1背包问题的最优解和最优值。 下面是使用回溯法解决0-1背包问题的示例代码: ```python def backtrack(i, cw, cv, weight, value, n, c): if i == n or cw == c: return cv if cw + weight[i] <= c: choose = backtrack(i+1, cw+weight[i], cv+value[i], weight, value, n, c) else: choose = 0 not_choose = backtrack(i+1, cw, cv, weight, value, n, c) return max(choose, not_choose) weight = [2, 3, 4, 5] value = [3, 4, 5, 6] n = len(weight) c = 8 max_value = backtrack(0, 0, 0, weight, value, n, c) print("The maximum value is:", max_value) ``` 该代码中,weight和value分别表示物品的重量和价值,n表示物品个数,c表示背包容量。运行代码后,会输出0-1背包问题的最优值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值