http://acm.hdu.edu.cn/showproblem.php?pid=2209
1.从第一个纸牌开始,将它的其他状态入队,
2.然后取队首元素,如果 是结果,则输出步数返回,否则重复1.
关键在于如何储存当前纸币的状态,一般字符串方法会TLE
#define N 1<<20
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<queue>
using namespace std;
bool vis[N];
int len,flag;
struct state{
int s;
int setp;
};
void bfs(int s)
{
queue<state> Q;
state p,k;
p.s = s;p.setp = 0;
Q.push(p);
vis[s]=1;
int q;
while(!Q.empty()){
p = Q.front(); Q.pop();
int tmp = p.s;
if(tmp ==0 ) {
flag = 1;
printf("%d\n",p.setp);return;
}
for(int i=1;i<=len;i++){
if(i==1) q = tmp^3; // 3二进制是11,最左边两个
else q = tmp^(7<<(i-2)); //7二进制是111; 翻转3个
q &= (1<<len)-1; //最右边的多翻转了,再次翻转回来
if(!vis[q]){
vis[q] = 1;
k.s = q;
k.setp = p.setp+1;
Q.push(k);
}
}
}
}
int main()
{
int s,i;
char tmp[22];
while(~scanf("%s",tmp)){
len = strlen(tmp);
s = 0;
for(i=0;i<len;i++)
s = (s<<1)+tmp[i]-'0'; //将初始字符串转换成int型
flag = 0;
memset(vis,0,sizeof(vis));
bfs(s);
if(!flag) puts("NO");
}
return 0;
}