JZYZOJ 1385 拉灯游戏 状态压缩 搜索

http://172.20.6.3/Problem_Show.asp?id=1385

 
刚开始想的时候一直以为同一排不同的拉灯顺序对结果是有影响的,手推了好多遍才发现拉灯结果只和拉的灯有关,这也要打表,可以说非常智障了。
如果从上向下寻找拉的灯,那么每一排全暗主要相关的是下一排(通过下一排补齐)和初始状态,而每一排的初始状态是和其本身和上一排有关的,那么只要找出第一排所有的拉灯方案(2^5种)然后对这几种方案模拟一遍找能全亮且步数最小的方案。
锻炼搜索能力的好题 
注意小于6步…交的时候没看见,日常眼瞎1/1。
 
代码
 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring>  
 4 #include<algorithm>  
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=(1<<5)+10;
 9 int a[6]={};
10 char ch[10]={};
11 int f[maxn]={};//第一行操作数量
12 int f1[maxn]={};//第一行操作对第二行的影响
13 int nn[maxn]={};//第一行操作后得到的数
14 //以上三个通过dfs计算
15 int aa[maxn]={};//下一行来填满这一行对下一行的影响
16 int bb[maxn]={};//对下下一行的影响
17 int z[maxn]={};//操作数量
18 //以上三个预处理
19 int ma=maxn-11;
20 void dfs1(int k,int num,int d,int z){
21     if(k>=5){
22         f[z]=d;f1[z]=z;nn[z]=num;
23         return;
24     }
25     int w=1<<k,w1;
26     if(k>=1)w1=(7<<(k-1))&ma;
27     else w1=7/2;
28     dfs1(k+1,num,d,z);
29     dfs1(k+1,num^w1,d+1,z^w);
30 }
31 int main(){
32     //freopen("wtf.in","r",stdin);
33     //freopen("wtf.out","w",stdout);
34     int T;scanf("%d",&T);
35     for(int i=0;i<=ma;i++){
36         int k=4;
37         for(int j=1;j<=5;j++){
38             int w=1<<k,w1;
39             if(k>=1)w1=(7<<(k-1))&ma;
40             else w1=7/2;
41             if((i&w)==0) aa[i]=aa[i]^w1,z[i]++;
42             k--;
43         }
44         bb[i]=(~i)&ma;
45     }
46     while(T-->0){
47         memset(a,0,sizeof(a));
48         for(int i=1;i<=5;i++){
49             scanf("%s",&ch);
50             for(int j=1;j<=5;j++){
51                 a[i]*=2;
52                 a[i]+=ch[j-1]-'0';
53             }
54         }memset(f,63,sizeof(f));
55         int da=f[1];
56         dfs1(0,a[1],0,0);
57         int ans=da;
58         for(int i=0;i<=ma;i++){
59             int nex1=aa[nn[i]],nex2=bb[nn[i]],bu=f[i]+z[nn[i]],num=f1[i],zz;
60             for(int j=2;j<=5;j++){
61                 num=num^a[j]^nex1;//初始状态
62                 nex1=aa[num];//填满需要几步
63                 if(j==5&&num==ma)ans=min(ans,bu);
64                 bu+=z[num];
65                 zz=nex2;nex2=bb[num];num=zz;//填满这一行对下下一行的影响
66             }
67         }
68         if(ans>6)printf("%d
",-1);
69         else printf("%d
",ans);
70     }
71     return 0;
72 }
View Code
原文地址:https://www.cnblogs.com/137shoebills/p/7787037.html