题意:一群人想点一个Pizza,每个人都提出一些条件,求出一个Pizza满足每个人至少一个要求。
分析:一共16中物品,每种放或不放,最多2^16中情况,用二进制表示一下就行。
我做的有些麻烦了,一开始没加剪枝1,TLE,加上剪枝1过的也很悬,2.440s。
剪枝1:如果这种选法选择了未出现的物品,则不符合条件。
剪枝2:如果满足了这个人的某一个条件,则不必再看其他条件是否满足
剪枝3:如果某个人所有的条件都不满足,则这种物品的选法不符合条件。
剪枝4:如果找到一个合适的情况,就不必在向下寻找
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cctype> 5 6 char str[1010][110]; 7 char ans[1010]; 8 bool vis[30]; 9 int cnt; 10 11 bool Judge( int n ) 12 { 13 for ( int i = 0; i < 17; ++i ) 14 if ( !vis[i] && ( ( 1 << i ) & n ) ) return false; 15 return true; 16 } 17 18 int main() 19 { 20 cnt = 0; 21 while ( gets(str[cnt]) != NULL ) 22 { 23 memset( vis, false, sizeof(vis) ); 24 while ( str[cnt][0] != '.' ) 25 { 26 int k = 0; 27 while ( str[cnt][k] != '\0' ) 28 { 29 if ( isalpha( str[cnt][k] ) ) 30 vis[ str[cnt][k] - 'A' ] = true; 31 ++k; 32 } 33 gets(str[++cnt]); 34 } 35 36 int i = 0; 37 bool find = false; 38 for ( ; i <= ( 1 << 16 ); ++i ) 39 { 40 if ( !Judge( i ) ) continue; //剪枝1 41 for ( int j = 0; j < cnt; ++j ) 42 { 43 int k = 0; 44 find = false; 45 while ( str[j][k] != '\0' ) 46 { 47 if ( isalpha(str[j][k]) ) 48 { 49 if ( str[j][k - 1] == '+' && ( i & ( 1 << (str[j][k] - 'A') ) ) ) 50 { 51 find = true; 52 break; //剪枝2 53 } 54 else if ( str[j][k - 1] == '-' && ( i & ( 1 << (str[j][k] - 'A') ) ) == 0 ) 55 { 56 find = true; 57 break; //剪枝2 58 } 59 } 60 ++k; 61 } 62 if ( !find ) break; //剪枝3 63 } 64 if ( find ) break; //剪枝4 65 } 66 67 if ( !find ) 68 { 69 puts("No pizza can satisfy these requests."); 70 cnt = 0; 71 continue; 72 } 73 74 int len = 0; 75 for ( int k = 0; k < 17; ++k ) 76 { 77 if ( ( 1 << k ) & i ) 78 ans[ len++ ] = k + 'A'; 79 } 80 ans[len] = '\0'; 81 82 printf( "Toppings:" ); 83 if ( len == 0 ) putchar('\n'); 84 else printf( " %s\n", ans ); 85 86 cnt = 0; 87 } 88 return 0; 89 }