拉灯游戏 搜索

你玩过“拉灯”游戏吗?25盏灯排成一个5×5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
  我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态

10111
01101
10111
10000
11011

  在改变了最左上角的灯的状态后将变成:

01111
11101
10111
10000
11011

  再改变它正中间的灯后状态将变成:

01111
11001
11001
10100
11011

  给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮

这也算是一道比较经典的问题了吧;

一种很快的做法是,枚举第一行改变了哪些灯的状态,然后我们就得到了第一行的灯的情况,然后为了满足末状态,第一行的未拉开的灯下面的那个灯一定要改变状态,这样就可以顺推下面的灯的状态,如果灯的状态都可以变成1,记录下步数比较即可;

第一遍的时候想如何暴力优化,想出了双向bfs搜索,可以先预处理下从末状态走三步的所有情况,然后在上面枚举的时候也只用走三步就可以了,25^3,枚举不会超过300,但由于常数比较大,容易被卡,我想出了双向bfs之后,便没有考虑在如何优化,上面的做法是后来知道的;

下面的是代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cstdlib>
 6 #include<ctime>
 7 #include<vector>
 8 #include<algorithm>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 #define LL long long
13 const int maxn=20,inf=1000000;
14 #define FILE "1"
15 #define upi,j,n) forint i=j;i<=n;i++)
16 #define downi,n,j) forint i=n;i>=j;i--)
17 namespace OI{
18     short int b[35000000],c[35000000];
19     int q[3000000],head,tail;//oj允许开这么大的数组我也是醉醉哒
20     int n;
21     inline int hint x,int y){return x*5+y-5;}
22     int dx[5]={0,0,0,-1,1},dy[5]={0,1,-1,0,0};
23     char ch[6][6];
24     int s;
25     void change){
26         s=0;
27         downi,5,1)upj,0,4){s=s<<1;ifch[i][j]=='1')s++;}
28     }
29     int ans=10;
30     void work){
31         //freopenFILE".in","r",stdin);
32         //freopenFILE".out","w",stdout);
33         scanf"%d",&n);
34         memsetc,10,sizeofc));
35         whilen--){
36             ans=10;
37             upi,1,5)scanf"%s",ch[i]);
38             change);
39             head=0,tail=0;q[++tail]=s;int x,y;c[s]=0;
40             int xx,yy;
41             while++head<=tail){
42                 x=q[head];
43                 ifb[x]<=3&&c[x]<=3)ans=minans,b[x]+c[x]);
44                 ifc[x]==3)continue;
45                 upi,1,5)upj,1,5){
46                     y=x;
47                     upk,0,4){
48                         xx=i+dx[k],yy=j+dy[k];
49                         ifxx<1||yy<1||xx>5||yy>5)continue;
50                         y=y^1<<hxx,yy)-1));
51                     }
52                     ifc[x]+1<c[y]){
53                         c[y]=c[x]+1;
54                         ifc[y]<3)q[++tail]=y;
55                         ifb[y]<=3&&c[y]<=3)ans=minans,b[y]+c[y]);
56                         ifc[y]==3)c[y]=90;
57                     }
58                 }
59             }
60             upi,1,tail)c[q[i]]=90;
61             printf"%d
",ans==10?-1:ans);
62         }
63     }
64     void first){
65         head=0,tail=0;int x,y;
66         q[++tail]=1<<25)-1;
67         memsetb,10,sizeofb));
68         b[1<<25)-1]=0;
69         int xx,yy;
70         while++head<=tail){
71             x=q[head];
72             ifb[x]==3)continue;
73             upi,1,5)upj,1,5){
74                 y=x;
75                 upk,0,4){
76                     xx=i+dx[k],yy=j+dy[k];
77                     ifxx<1||yy<1||xx>5||yy>5)continue;
78                     y=y^1<<hxx,yy)-1));
79                 }
80                 ifb[x]+1<b[y]){
81                     b[y]=b[x]+1;
82                     ifb[y]<3)q[++tail]=y;
83                 }
84             }
85         }
86     }
87 }
88 int main){
89     using namespace OI;
90     first);
91     work);
92     //printf"%d
",clock));
93     return 0;
94 }

View Code

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注