hdu 2209 -- 翻纸牌游戏
翻纸牌游戏
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2086 Accepted Submission(s): 747
Problem Description
有
一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是
麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个
乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
Input
有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
Sample Input
01
011
Sample Output
NO
1
原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=2209
思路:利用位运算搜索(枚举)即可
这是我ac代码 跑了593ms
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #define M (1<<21) 6 using namespace std; 7 int cnt[M]; 8 int BFS(int n,int m) 9 { 10 11 int t; 12 queue<int>pq; 13 cnt[n] = 1; 14 pq.push(n); 15 while(!pq.empty()){ 16 int v = (3<<(m-2)); 17 int vv = (7<<(m-3)); 18 int num = pq.front(); 19 pq.pop(); 20 for(int i = 1; i <= m; i++){ 21 if(i == 1){ 22 t = num^v; 23 if(t == 0){ 24 cnt[t] = cnt[num]; 25 return cnt[t]; 26 } 27 if(!cnt[t]){ 28 cnt[t] = cnt[num]+1; 29 pq.push(t); 30 } 31 } 32 else{ 33 t = num^vv; 34 if(t == 0){ 35 cnt[t] = cnt[num]; 36 return cnt[t]; 37 } 38 if(!cnt[t]){ 39 cnt[t] = cnt[num]+1; 40 pq.push(t); 41 } 42 vv = vv>>1; 43 } 44 45 } 46 } 47 return -1; 48 } 49 int main() 50 { 51 char str[25]; 52 while(cin>>str){ 53 memset(cnt,0,sizeof(cnt)); 54 int number = 0,steps; 55 int len = strlen(str); 56 for(int i = 0; str[i]; i++){ 57 number = number << 1; 58 if(str[i] == '1'){ 59 number = number | 1; 60 } 61 } 62 if(number == 0){ 63 printf("0\n"); 64 continue; 65 } 66 if(len == 1){ 67 if(number == 1){ 68 printf("1\n"); 69 continue; 70 } 71 } 72 if(len == 2){ 73 if(number == 3){ 74 printf("1\n"); 75 } 76 else{ 77 printf("NO\n"); 78 } 79 continue; 80 } 81 steps = BFS(number,len); 82 if(steps == -1){ 83 printf("NO\n"); 84 } 85 else{ 86 printf("%d\n",steps); 87 } 88 } 89 return 0; 90 }
下面是网上0ms代码,orz。。。
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <math.h> 5 #include <stdlib.h> 6 using namespace std; 7 const int inf = 1<<30; 8 9 char str[30]; 10 int a[30]; 11 12 int DFS(int i,int len,int m) 13 { 14 if(i == len) 15 return a[i-1]?inf:m; 16 if(a[i-1]) 17 { 18 a[i-1] = !a[i-1]; 19 a[i] = !a[i]; 20 a[i+1] = !a[i+1]; 21 m++; 22 } 23 DFS(i+1,len,m); 24 } 25 26 int main() 27 { 28 int i,ans,len; 29 while(~scanf("%s",str)) 30 { 31 len = strlen(str); 32 ans = inf; 33 for(i = 0; i<len; i++) 34 a[i] = str[i]-48; 35 a[0]=!a[0]; 36 a[1]=!a[1]; 37 ans = min(ans,DFS(1,len,1));//第一张牌翻转 38 for(i = 0; i<len; i++) 39 a[i] = str[i]-48; 40 ans = min(ans,DFS(1,len,0));//第一张牌没有手动翻转 41 if(ans == inf) 42 printf("NO\n"); 43 else 44 printf("%d\n",ans); 45 46 } 47 48 return 0; 49 }
Do one thing , and do it well !