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 }