周鹏飞
(丽水学院 工学院 计112本,浙江 丽水 323000)
摘要:针对如何利用计算机来解决点灯游戏的问题,点灯游戏在ACM的题型中也是一类,可以采用搜索来解决,但是也可以采用线性代数中的高斯消元法来解决。先求出灯组矩阵的系数矩阵,然后列出增广矩阵。采用异或操作,求出方程的解。
关键字:高斯消元法;国际大学生程序设计竞赛(ACM);点灯游戏;灯光师小明;
0 引言
在南阳理工学院ACM系统上有着这么一道有趣的题目《灯光师小明》
灯光师小明
时间限制:1000 ms |内存限制:65535 KB
难度:1
描述
灯光师小明控制着各种晚会的各种大小灯,每次晚会小明都会对灯进行很多次操作。对每盏灯只能进行两种操作,开和关。现在小明希望自己随时都知道还有多少盏灯亮着。你需要编写一个程序当小明问你时你能快速的说出还有多少盏灯亮着,晚会开始时所有的灯都是灭的。
输入
只有一组数据第一行输入两个正整数N,T(0<N<=100000,0<T<=1000000)N表示有N盏灯,T表示有T条指令。随后T行每行有一条指令,这条指令包含一个字符串,当字符串为CHANGE,它后面还有一个整数m,表示对第m盏灯进行一次操作(操作表示如果第m盏灯灯是开着时就关闭,如果灯是关着时就打开)。当字符串为QUERY,表示小明想查询现在还有多少盏灯亮着。
输出
每次查询指令输出占一行,输出当前亮着灯的个数
样例输入
10 8
CHANGE 1
QUERY
CHANGE 2
QUERY
CHANGE 1
CHANGE 9
CHANGE 7
QUERY
样例输出
1
2
3
这一道题目非常的简单,之所以引出这么一道题目,是让大家先对点灯操作有个了解。下面是我对该题目的一个解法:
http://acm.nyist.net/JudgeOnline/problem.php?pid=224
#include <stdio.h>
int main()
{
intN, T, num;
intwork = 0;
intlight[100000];
for(int i = 0; i < 100000; i++)
light[i]= 0;
charorder[10];
scanf("%d%d",&N, &T);
while(T--){
scanf("%s",order);
if(order[0] == 'C'){
scanf("%d",&num);
if(light[num] == 1){
light[num]= 0;
work--;
}
else{
light[num]= 1;
work++;
}
}
else{
printf("%d\n",work);
}
}
}
对于真正的点灯游戏问题这个真的是太简单了
下面引出我从百度贴吧里找到的一个题目:
http://tieba.baidu.com/f?kz=945725034
题目是这样的,给你一个4*4的灯组,灯组中每盏灯的初始状态不定(即开始时不一定是全关),当改变任意一盏灯时,该灯所在的行上和列上的所有灯状态一起改变,例如
初始灯组状态是这样的:
1000
0111
0111
0111
改变了第一盏灯的状态以后,灯组变为了
0111
1111
1111
1111
(1代表开,0代表关)
现在给你一个灯组,求使这个灯组所有灯全部打开的最少步骤
例如input
1011
1111
1111
1011
OUPUT
6(改变了(1,1),(1,3),(1,4),(4,1),(4,3),(4,4))
然后再在excel上列出本题的一个基本框图,该矩阵的解即为,即为所需操作:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
2 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
3 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
1< |