首页 > 代码库 > HDU 2209 翻纸牌游戏(dfs)

HDU 2209 翻纸牌游戏(dfs)

翻纸牌游戏

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2180    Accepted Submission(s): 787


Problem Description
有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
 

 

Input
有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
 

 

Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
 

 

Sample Input
01
011
 

 

Sample Output
NO
1
 
 
 
 
 
每张牌由三张牌决定(不包括首位两张牌),对于第 i 张牌,若不考虑其后面一张牌只考虑其前面一张牌,那么由第i-1牌的状态可以决定第 i 张牌翻不翻,(由于翻牌时对一张牌翻多次没必要,所以每张牌只是两种情况:翻或者不翻),若第i-1张牌是反面,那么把i-1、i、i+1都翻一次,否则都不翻 ,向后(对i+1)进行前面操作,显然初始状态是 第 1 张牌翻还是不翻,对这两种状态都进行一次上述操作,看哪种状态下可以得到我们所需要的状态。  结束时只判断最后一张牌是否是正面即可(第 i 张牌前面的所有牌在 i 之前的操作中全变成正面朝上)。
 
 
代码:
 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 #define inf 999999999 7  8 int a[22]; 9 char c[22];10 int n;11 12 13 int dfs(int k,int step){14 15     if(k>=n){16         return a[k-1]?inf:step;17         18     }19     if(a[k-1]){          //若第K张牌前面一张牌为反面,那么需要翻第k张牌使得第k-1张牌正面朝上 20         a[k-1]=0;21         a[k]=!a[k];22         a[k+1]=!a[k+1];23             step++;24     }25     return dfs(k+1,step);26 }27 28 main()29 {30     int i, j;31     while(scanf("%s",c)!=EOF){32          n=strlen(c);33          for(i=0;i<n;i++) a[i]=c[i]-0;34          a[0]=!a[0];a[1]=!a[1];            //翻第一张牌 35          int num=inf;36          37          num=min(num,dfs(1,1));      38          for(i=0;i<n;i++) a[i]=c[i]-0; 39          num=min(num,dfs(1,0));          //不翻第一张牌 40          if(num==inf) printf("NO\n");41          else printf("%d\n",num); 42     }43 }