翻纸牌游戏
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
Input
有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。
Output
对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。
Sample Input
01
011
Sample Output
NO
1
0^1 = 1
1^1 = 0
[][][][][][][]
^ 1100000
^ 0111000
^ 0011100
^ 0001110
^ 0000111
^ 0000011
#include <iostream> #include <string> #include <string.h> #include <map> #include <stdio.h> #include <algorithm> #include <queue> #include <vector> #include <math.h> #include <set> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std ; typedef long long LL ; bool visited[1<<20] ; class App{ private : string st ; int st_num ; int Len ; struct Node{ int X ; int step ; friend bool operator < (const Node A ,const Node B){ return A.step > B.step ; } Node(){} Node(int x ,int s):X(x),step(s){} }; public : App() ; App(string ) ; int bfs() ; }; App::App(){ } App::App(string s):st(s){ memset(visited,0,sizeof(visited)) ; st_num = 0 ; Len = st.length() ; for(int i = 0 ; i < Len ; i++) st_num = (st_num<<1) + (st[i]-'0') ; visited[st_num] = 1 ; } int App::bfs(){ priority_queue<Node> que ; que.push(Node(st_num,0)) ; while(!que.empty()){ Node now = que.top() ; int x = now.X ,nx ; int s = now.step ; if(x == 0) return s ; que.pop() ; nx = x^3 ; if(!visited[nx]){ visited[nx] = 1 ; que.push(Node(nx,s+1)) ; } for(int i = 0 ; i <= Len -3 ; i++){ nx = (7<<i)^x ; if(!visited[nx]){ visited[nx] = 1 ; que.push(Node(nx,s+1)) ; } } nx = (3<<(Len-2))^x ; if(!visited[nx]){ visited[nx] = 1 ; que.push(Node(nx,s+1)) ; } } return -1 ; } int main(){ string s ; while(cin>>s){ App app(s) ; int step = app.bfs() ; if(step == -1) puts("NO") ; else printf("%d ",step) ; } return 0 ; }