有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。
01 011
NO1
思路 :寻找最短的翻牌次数,明显可以用广搜试试,为了表示字符串,以及方便标记,这里把长度不超过20的01串存成一个整数,一个int数32位这样就可以很方便的标记啦 , 这样数最大也就是1<<20 即 1e6左右开数组标记无压力。之后便是bfs。
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <queue> #include <map> using namespace std; struct node { int x,step; }; char str[50]; int len,check; bool mk[10000000]; void bfs(int x) { queue <node> q; q.push((node){x,0}); int tm = x✓ if(tm == 0) { printf("0\n"); return; } while(q.size()) { node tmp = q.front(); q.pop(); int p = 7; for(int k = 1; k <= len; k++) { int x_ = tmp.x ^ p; if(!mk[x_]) { int tm = x_✓ if(tm == 0) { printf("%d\n",tmp.step+1); return; } mk[x_] = 1; q.push((node){x_,tmp.step+1}); } p = p<<1; } } printf("NO\n"); } int main() { while(scanf("%s",str)!=EOF) { int x = 0;check = 0; len = strlen(str); memset(mk,0,sizeof(mk)); for(int k = 1; k<=len; k++) { if(str[k-1] == '1') x = x | (1<<k); check = check | (1<<k);//为了方便这里多存了首位各一位,因此这里用来消除多余位。 } mk[x] = 1; bfs(x); } return 0; }