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\n",-1);
69         else printf("%d\n",ans);
70     }
71     return 0;
72 }

时间: 2024-10-29 19:07:58

JZYZOJ 1385 拉灯游戏 状态压缩 搜索的相关文章

拉灯游戏 搜索

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

HDU 1885 Key Task 状态压缩+搜索

点击打开链接 Key Task Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1176    Accepted Submission(s): 462 Problem Description The Czech Technical University is rather old - you already know that it c

POJ 1632 Vase collection【状态压缩+搜索】

题目传送门:http://poj.org/problem?id=1632 Vase collection Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2308   Accepted: 901 Description Mr Cheng is a collector of old Chinese porcelain, more specifically late 15th century Feng dynasty vase

Codeforces3C. Tic-tac-toe 题解 状态压缩+搜索

题目链接:https://codeforces.com/contest/3/problem/C 题目大意: 有一个 \(3 \times 3\) 的棋盘,给你一个棋盘当前的状态,请你输出当前这个状态对应的描述. 解题思路: \(3 \times 3\) 的棋盘上一共有9个位置,每个位置只有可能是3种状态:"."."0"或"X". 所以总的状态数有 \(3^9\) 种,我们可以从初始状态开始来搜索遍历得到所有的状态对应的描述(如果一个状态通过搜索遍

CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)

这题我在考场上也是想出了正解的……但是没调出来. 题目链接:CF原网 题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值. $1\le n\le 4\times 10^5,1\le q\le 2\times 10^5,1\le a_i,x\le 300$.时限 5.5s,空限 256MB. 明显线段树. 有一个想法是维护区间积的欧拉函数,但是这样时间复杂度和代码复杂度都很高…… 我的做法是维护区间积.而欧拉函数,就是看看

ZOJ 3814 Sawtooth Puzzle 状态压缩搜索

由于一个框框只有4种状态,总状态数只有4^9,bfs可解. 麻烦的地方就在于模拟. 我的状态的存法是,将初始状态看做000000000,若顺时针旋转一次就+1, 3+1=0. bfs的过程中,需要套一个dfs计算旋转当前框框会影响到哪些框. 有个地方要注意,就是目标状态其实不止一种,因为有些框框旋转之后不变,我们必须把所有可能的目标状态都计算出来,样例的中间那个框框就是这种情况. #include <iostream> #include<cstdio> #include<al

hdu 4771 状态压缩搜索

基本上和胜利大逃亡一样!!!!!!!! #include<stdio.h> #include<string.h> #include<queue> #include<iostream> using namespace std; int mark[110][110][1<<6],n,m; char map[110][110]; int leap[110][110]; struct node { int x,y,step; int state; int

hdu4845 状态压缩搜索水题

这道题简单来说是和胜利大逃亡续类似的题  只不过这道题没有给你明确的地图 只给了你点之间的关系          唯一的坑点在于一个点可能有多把钥匙 #include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; struct node { int x,y,step,state; }a,b; int mark[16][16][3030];

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物