您的位置:首页 > 其它

POJ 1222 熄灯问题

2013-01-21 23:07 260 查看
考察知识点:遍历搜索空间,枚举

解题思路:

用数组元素

(1) puzzle[i][j]表示位置(i, j)上灯的初始状态:1 表示灯是被点亮的;0 表示灯是熄灭的。用数组

元素press[i][j]表示为了让全部的灯都熄灭,是否要按下位置(i, j)上的按钮:1 表示要按下;

0 表示不用按下。由于第0 行、第0 列和第7 列不属于按钮矩阵的范围,没有按钮,可以假

设这些位置上的灯总是熄灭的、按钮也不用按下。


(2) 根据熄灯规则,如果矩阵press 是寻找的答案,那么按照press 的第一行对矩阵中的按钮

操作之后,此时在矩阵的第一行上:

*如果位置(1, j)上的灯是点亮的,则要按下位置(2, j)上按钮,即press[2][j]一定取1;

*如果位置(1, j)上的灯是熄灭的,则不能按位置(2, j)上按钮,即press[2][j]一定取0。

这样依据press 的第一、二行操作矩阵中的按钮,才能保证第一行的灯全部熄灭。而对矩阵

中第三、四、五行的按钮无论进行什么样的操作,都不影响第一行各灯的状态。依此类推


(3) 函数guess(),做两件事件。(1)根据press 第一行和puzzle

数组,按照熄灯规则计算出press 其他行的值,使得矩阵第1~4 行的所有灯都熄灭。(2)判断

所计算的press 数组能否熄灭矩阵第5 行的所有灯。如果能够就返回“true”,表示找到了答

案;否则返回“false”,表示没有找到答案。


(4)函数enumate(),对press 第一行的元素press[1][1]~ press

[1][6]的各种取值情况进行枚举。在每种取值情况下,分别调用guess(),看看是否找到了答

案。如果找到了答案,就返回主函数,否则继续下一种取值情况的判断


#include <stdio.h>

int puzzle[6][8];
int press[6][8];

bool guess()  //guess函数由第一行和PUZZLE数组计算其他行的press数组
{
int c,r; //行和列
for(r=1; r<5; r++)
for(c=1; c<7; c++)
press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;

for(c=1; c<7; c++) //guess函数还可以用计算得到的数组判断是否能关闭第五行
if((press[5][c-1]+press[5][c]+press[5][c+1]+press[4][c])%2!=puzzle[5][c])
return (false);

return (true);

}
void enumate()  //对press[1][1]~~press[1][6]  一行各列进行枚举并调用guess看是否 那个,你懂得
{
int c;
for(c=1; c<7; c++)
press[1][c]=0;

while(guess()==false)
{
press[1][1]++;
c = 1;
while(press[1][c]>1)
{
press[1][c]=0;
c++;
press[1][c]++;
}
}
return ;
}

int main()
{
freopen("in.txt","r",stdin);
int cases,i,r,c;
scanf("%d",&cases);
for(r=0; r<6; r++)
puzzle[r][0]=0;
for(c=1; c<7; c++)
puzzle[0][c]=0;

for(i=0; i<cases; i++)
{
for(r=1; r<6; r++)
for(c=1; c<7; c++)
scanf("%d",&puzzle[r][c]);

enumate();
printf("PUZZLE #%d\n",i+1);

for(r=1; r<6; r++)
{
for(c=1; c<7; c++)
printf("%d",press[r][c]);
printf("\n");
}
}
return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: