HDOJ搜索专题之翻纸牌游戏

BFS,数学模型如下:

对于一个01序列(长度小于20),定义翻转操作为:选定序列中的一位,将其取反,并将其左右相邻的位(如果存在)取反,现给定一个初始序列,求最少需操作多少次使得序列变成全0序列。

分析:序列状态可用一个32位整数表示,状态数目最多为220,所以搜索不会超时,翻转操作可用异或运算来表示。

需注意的是,写好后别忘了测试n=1的情况。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <math.h>
 4 #include <queue>
 5 using namespace std;
 6 typedef struct node
 7 {
 8   int s,t;
 9 }node;
10 queue<node> S;
11 node cur,next;
12 int d[20];
13 char s[21];
14 char vis[1<<20];
15 void bfs()
16 {
17   int i,ans;
18   bool success=false;
19   while(!S.empty()) S.pop();
20   memset(vis,0,sizeof(vis));
21   cur.t=0;
22   vis[cur.s]=1;
23   S.push(cur);
24   while(!S.empty()&&!success)
25   {
26     cur=S.front(),S.pop();
27     if(cur.s==0)  success=true,ans=cur.t;
28     for(i=0;i<20&&!success;i++)
29     {
30       next=cur;
31       next.t++;
32       next.s^=d[i];
33       if(next.s==0) success=true,ans=next.t;
34       else if(!vis[next.s])
35       {
36         vis[next.s]=1;
37         S.push(next);
38       }
39     }
40   }
41   if(success) printf("%d\n",ans);
42   else  puts("NO");
43 }
44 int main()
45 {
46   int i,n;
47   while(gets(s))
48   {
49     n=strlen(s);
50     d[0]=3;
51     if(n>1)
52     {
53       d[n-1]=3<<(n-2);
54       if(n>2) d[1]=3;
55       else  d[1]=7;
56       for(i=2;i<n-1;i++) d[i]=d[i-1]<<1;
57     }
58     cur.s=0;
59     for(i=0;i<n;i++)
60     {
61       cur.s=(cur.s<<1)+s[i]-'0';
62     }
63     if(n==1&&cur.s==1)  puts("1");
64     else  bfs();
65   }
66   return 0;
67 }
原文地址:https://www.cnblogs.com/algorithms/p/2504200.html