pku 1222 EXTENDED LIGHTS OUT 解题报告
一、题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=1222
二、题意:给出5行6列的0、1数列,表示灯亮与否,1表示灯亮,0表示灯不亮。按下一个灯,则其上下左右的灯也会相反,即1变0,0变1.求按下那些灯,使全部的灯都不亮?
三、解题思路:
此题想了挺久,看看网上acm训练计划,说好像使用到了高斯消去法,可本人我无论怎么样都想不出与高斯消去法相联系起来。希望牛人告诉我。
我主要是看中了一个条件,按下一个灯,则影响上下左右的灯。仔细用笔写写,发现只要确定其中第一行,你们其他的行都可以确定。比如sample中,确定了1 0 1 0 0 1,那么第二行就变为0 0 1 1 1 0,确定第二行就容易多了。因为这5个灯(搜索到灯以及其上下左右的灯),其第五个即下的那一个灯,就是上面灯的原状态加上其对应的上左右结果的和%2。用C语言表达:
for (j = 2; j <= 5; j++)
{
for (k = 1; k <= 6; k++)
{
result[j][k] = (puzzle[j - 1][k] + result[j - 2][k] + result[j - 1][k] + result[j - 1][k - 1] + result[j - 1][k + 1]) % 2;
}
}
那么解决了这一步就好办多了。
四、AC代码:
#include <stdio.h>
#include <string.h>
int puzzle[7][8], result[7][8];
int check(int result[][8])
{
int i, j, k, temp[7][8] = {0};
//temp用于计算随着灯的按下,其相应的结果
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= 6; j++)
{
temp[i][j] = puzzle[i][j];
}
}
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= 6; j++)
{
//遇到灯必须按下的,那么其上下左右都要按下
if (result[i][j])
{
temp[i][j] = (temp[i][j] == 1) ? 0 : 1;
temp[i - 1][j] = (temp[i - 1][j] == 1) ? 0 : 1;
temp[i][j - 1] = (temp[i][j - 1] == 1) ? 0 : 1;
temp[i][j + 1] = (temp[i][j + 1] == 1) ? 0 : 1;
temp[i + 1][j] = (temp[i + 1][j] == 1) ? 0 : 1;
}
}
}
//判断是否符合要求
for (j = 1; j <= 5; j++)
{
for (k = 1; k <= 6; k++)
{
if (temp[j][k])
{
return 0;
}
}
}
return 1;
}
int main()
{
freopen("1.txt", "r", stdin);
int i, j, k, temp;
int test, count = 1;
scanf("%d", &test);
while (test--)
{
memset(result, 0, sizeof(result));
for (i = 1; i <= 5; ++i)
{
for (j = 1; j <= 6; ++j)
{
scanf("%d", &puzzle[i][j]);
}
}
for (i = 0; i < 64; i++)
{
//转换为二进制
for (j = 6, temp = i; j >= 1; j--)
{
result[1][j] = temp % 2;
temp /= 2;
}
//确定下面的结果
for (j = 2; j <= 5; j++)
{
for (k = 1; k <= 6; k++)
{
result[j][k] = (puzzle[j - 1][k] + result[j - 2][k] + result[j - 1][k] + result[j - 1][k - 1] + result[j - 1][k + 1]) % 2;
}
}
//判断是否符合要求
if (check(result))
{
break;
}
}
//打印
printf("PUZZLE #%d/n", count++);
for (i = 1; i <= 5; i++)
{
for (j = 1; j <= 6; j++)
{
printf("%d ", result[i][j]);
}
printf("/n");
}
}
return 0;
}
其实按我的代码来看使比较丑陋的,如果数据很大的时候,那么我的代码一定是要超时的。看了牛人的代码,让我佩服,也自己觉得差距很大啊····
PS:如果有人知道怎么用到高斯消去法解决此题,望告诉我一下·谢谢·(*^__^*) ~