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;
}

浙公网安备 33010602011771号