POJ 1222 EXTENDED LIGHTS OUT 枚举
题意:灯泡构成的5*6的矩阵,每个灯泡有亮或不亮两种状态,每按下一个开关变换一个灯泡的状态,它的上下左右也要变换,最后让所有的灯都熄灭
输出按下开关的矩阵
如果模拟枚举的话2^30种情况,会超时
超时代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; int map[8][8]={0},press[8][8]={0}; int n=5,m=6,ca; bool fg; void change(int x) { int i,j; i=x/6; j=x%6; map[i][j]^=1; if(i>=1)map[i-1][j]^=1; if(i<=3)map[i+1][j]^=1; if(j>=1)map[i][j-1]^=1; if(j<=4)map[i][j+1]^=1; } bool judge() { int i,j; for(i=0;i<n;i++) for(j=0;j<m;j++) if(map[i][j]==1)return 0; return 1; } void dfs(int x) { if(x>=30)return; if(fg=judge())return ; if(fg)return ; change(x); press[x/6][x%6]=1; dfs(x+1); if(fg)return ; press[x/6][x%6]=0; change(x); dfs(x+1); } int main() { int CASE,i,j; scanf("%d",&CASE); for(ca=1;ca<=CASE;ca++) { for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&map[i][j]); fg=0; memset(press,0,sizeof(press)); dfs(0); printf("PUZZLE #%d\n",ca); for(i=0;i<n;i++) { for(j=0;j<m-1;j++) printf("%d ",press[i][j]); printf("%d\n",press[i][j]); } } return 0; }
枚举第一行按开关的状态(2^6中),然后为了让第一行的灯全灭掉,第二行的开关有一个确定的状态,然后第三行的开关也有确定的状态。。。直到让第四行的灯全熄灭,第五行的开关有确定的状态,这时开关的状态都确定了 ,检查最后一行(第五行)的灯是否全熄灭 。 递归枚举第一行的状态 (枚举一行或一列的思想 poj 3600)
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; int map[8][8]={0},press[8][8]={0}; int n=5,m=6,ca; bool fg; bool judge() { bool f=0; int i,j; for(i=2;i<=n;i++) for(j=1;j<=m;j++) press[i][j]=(map[i-1][j]+press[i-1][j-1]+press[i-1][j]+ press[i-1][j+1]+press[i-2][j])%2; for(i=1;i<=m;i++) if((press[5][i-1]+press[5][i]+press[5][i+1]+ press[4][i]+map[5][i])%2==1)return 0; return 1; } void dfs(int x) { if(x>=7){fg=judge();return;} if(fg)return ; press[1][x]=0; dfs(x+1); if(fg)return ; press[1][x]=1; dfs(x+1); } int main() { int CASE,i,j; scanf("%d",&CASE); for(ca=1;ca<=CASE;ca++) { for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&map[i][j]); fg=0; dfs(1); printf("PUZZLE #%d\n",ca); for(i=1;i<=n;i++) { for(j=1;j<m;j++) printf("%d ",press[i][j]); printf("%d\n",press[i][j]); } } return 0; }