Uva--565((回溯,搜索,剪枝)

2014-07-19 20:54:33

思路:枚举每个topping,放或不放,要注意Dfs之后要还原数据(不知道自己写的还原有没有点多余的部分)。

主要剪枝:先记录每个人的所有需求中的最大字母Ki(如:+H+I+C; 的最大字母是I),当递归到第cur个字母时,搜索所有人,如果某个人的需求未被至少满足一条,且他的Ki < cur,那么之后

他的需求也不可能被满足,剪枝。

  1 /*************************************************************************
  2     > File Name: Uva565.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Sat 19 Jul 2014 03:06:46 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 const int RA = 16; // total number of topping
 16 
 17 char s[50][30];
 18 int cnt,g[50][20],to[20],used[50],tmax[50];
 19 
 20 bool Dfs(int cur,int num){
 21     if(num >= cnt)
 22         return true;
 23     if(cur >= RA)
 24         return false;
 25     // do not add top
 26     int used2[50] = {0};
 27     for(int i = 0; i < cnt; ++i){
 28         if(used[i]) continue;
 29         if(g[i][cur] == -1){
 30             used[i] = 1;
 31             used2[i] = 1;
 32             ++num;
 33         }
 34         else if(tmax[i] < cur)
 35             return false;
 36     }
 37     if(Dfs(cur + 1,num))
 38         return true;
 39     for(int i = 0; i < cnt; ++i){
 40         if(used2[i]){
 41             used[i] = 0;
 42             --num;
 43         }
 44     }
 45     //add top
 46     memset(used2,0,sizeof(used2));
 47     for(int i = 0; i < cnt; ++i){
 48         if(used[i]) continue;
 49         if(g[i][cur] == 1){
 50             used[i] = 1;
 51             used2[i] = 1;
 52             ++num;
 53         }
 54         else if(tmax[i] < cur)
 55             return false;
 56     }
 57     to[cur] = 1;
 58     if(Dfs(cur + 1,num))
 59         return true;
 60     to[cur] = 0;
 61     for(int i = 0; i < cnt; ++i){
 62         if(used2[i]){
 63             used[i] = 0;
 64             --num;
 65         }
 66     }
 67     return false;
 68 }
 69 
 70 void Init(){
 71     cnt = 0;
 72     memset(g,0,sizeof(g));
 73     memset(to,0,sizeof(to));
 74     memset(used,0,sizeof(used));
 75     memset(tmax,0,sizeof(tmax));
 76 }
 77 
 78 int main(){
 79     Init();
 80     while(scanf("%s",s[cnt]) == 1){
 81         if(s[cnt][0] == '.'){
 82             if(Dfs(0,0)){
 83                 printf("Toppings: ");
 84                 for(int i = 0; i < RA; ++i)
 85                     if(to[i]) printf("%c",'A' + i);
 86                 printf("\n");
 87             }
 88             else printf("No pizza can satisfy these requests.\n");
 89             Init();
 90             continue;
 91         }
 92         // deal with the No.cnt person
 93         int len = strlen(s[cnt]);
 94         for(int i = 0; i < len - 2; i += 2){
 95             if(s[cnt][i] == '-')
 96                 g[cnt][s[cnt][i + 1] - 'A'] = -1; // -1 : dislike
 97             else
 98                 g[cnt][s[cnt][i + 1] - 'A'] = 1; // 1 : like
 99             tmax[cnt] = max(tmax[cnt],s[cnt][i + 1] - 'A');
100         }
101         ++cnt; // cnt : the total number of persons
102     }
103     return 0;
104 }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值