Author : Evensgn 
Blog Link : http://www.cnblogs.com/JoeFan/
Article Link : http://www.cnblogs.com/JoeFan/p/4338003.html
 

游戏介绍

Lights Out (关灯)是一款据说在20世纪90年代就已经被设计出的小游戏,游戏的玩法十分简单。

首先,给定一个 n 行 m 列的矩形方格阵,每个格子上都有一盏灯。

初始时,有些灯是开着的,有些灯是关着的。

玩家每次进行一次操作,选中一盏灯,点击一下它,就会将它和与它相邻的灯的状态改变,即开着的灯变为关闭,关着的灯变为开启。

最后的目的是关闭所有的灯。

这里给出一个网页版的链接:关灯

还有博客园一位博友DIY的一个类似的游戏,蓝色拼图。这个蓝色拼图与 Lights Out 实质上相同,只是初始状态固定了是所有的灯都是开启的。

Lights Out 的游戏规则就是这样简单,然而到了后面的几关,方格增多,情况复杂,人工找出解法对于我来说是十分困难的。

因此,我们考虑用程序求解这个游戏。

求解方法

首先我们要将这个游戏的过程转化为数学模型。

显然地,对于一个方格,会影响到它的方格只有它本身和与它相邻的 4 个方格(对于边界的方格来说,相邻的方格不足 4 个)。

并且很容易发现,每一个方格我们要么不点击,要么点击 1 次,因为点击一个方格两次及以上是没有任何意义的。每点击两次就相当于没有点击。

对于方格 i ,我们用 0 表示不点击它,用 1 表示点击它,记作 Si 。

每盏灯的状态只有开或者关,我们用 0 和 1 表示方格 i 状态,方格 i 的初始状态记为 Mi 。

可以看出,每盏灯 i 的最终状态只与 Mi + Si + Sk1 + Sk2 + .... + Skp  (k1 ... kp 是枚举与 i 相邻的所有方格)的奇偶性有关。

既然只与奇偶性有关,我们就可以用异或运算来表示它。

也就是说,对于每盏灯 i ,我们都可以得到一个方程       Mi xor Si xor Sk1 xor Sk2 xor ... xor Skp = 0 。

等式右边的 0 表示最后每盏灯的状态都是关闭的。

这个方程其实也就等价于        Si xor Sk1 xor Sk2 xor ... xor Skp = Mi 。

我们得到了 Tot 个这样的方程(Tot 是灯的数量,即 Tot = n * m),共有 Tot 个未知数(即 Tot 个 Si),就是一个异或方程组。

由于游戏给定的初始状态一定有解,所以我们是一定可以求出这个异或方程组的一组解的。

那么下面的问题就是:怎样求解异或方程组?

显然,我们要使用高斯消元来求异或方程组的解。

这个过程与使用高斯消元求解普通的线性方程组相似(如果不了解高斯消元可以看一下Wikipedia-高斯消去法),只是每次在一个方程中消去一个未知数的时候,不是将这个方程乘上一个系数后与另一个方程相减,而是将这个方程的系数与另一个方程的系数进行异或运算,两个方程右边的数也要一起进行异或。

这样就可以求出 Lights Out 的解了。

代码如下,因为代码非常简单所以没有添加注释:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; const int MaxL = 10 + 5, MaxN = 100 + 5;
const int Dx[5] = {0, 0, 1, -1}, Dy[5] = {1, -1, 0, 0}; int n, m, Tot;
int A[MaxN][MaxN], Map[MaxL][MaxL], Ans[MaxL][MaxL]; inline bool Inside(int x, int y)
{
if (x < 0 || x >= n) return false;
if (y < 0 || y >= m) return false;
return true;
} inline int Get_Index(int x, int y)
{
return x * m + y + 1;
} struct Pos
{
int x, y;
}; inline Pos Get_Pos(int Num)
{
Pos ret;
ret.x = (Num - 1) / m;
ret.y = ((Num % m - 1) + m) % m;
return ret;
} void Get_Equation(int x, int y)
{
int Id, Id2, xx, yy;
Id = Get_Index(x, y);
for (int i = 1; i <= Tot; ++i) A[Id][i] = 0;
A[Id][Tot + 1] = Map[x][y];
A[Id][Id] = 1;
for (int k = 0; k < 4; ++k)
{
xx = x + Dx[k]; yy = y + Dy[k];
if (!Inside(xx, yy)) continue;
Id2 = Get_Index(xx, yy);
A[Id][Id2] = 1;
}
} inline void Swap(int p, int q)
{
int Temp;
for (int i = 1; i <= Tot + 1; ++i)
{
Temp = A[p][i];
A[p][i] = A[q][i];
A[q][i] = Temp;
}
} void Gauss()
{
int Tj;
for (int i = 1; i <= Tot; ++i)
{
Tj = i;
for (int j = i + 1; j <= Tot; ++j)
{
if (A[Tj][i] == 0 && A[j][i] == 1)
{
Tj = j;
break;
}
}
if (A[Tj][i] == 0) continue;
if (Tj != i) Swap(Tj, i);
for (int j = i + 1; j <= Tot; ++j)
{
if (A[j][i] == 0) continue;
for (int k = i; k <= Tot + 1; ++k)
A[j][k] ^= A[i][k];
}
} Pos Pi;
for (int i = Tot; i >= 1; --i)
{
Pi = Get_Pos(i);
Ans[Pi.x][Pi.y] = A[i][Tot + 1];
for (int j = i - 1; j >= 1; --j)
if (A[j][i]) A[j][Tot + 1] ^= A[i][Tot + 1];
}
} int main()
{
scanf("%d%d", &n, &m);
Tot = n * m;
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
scanf("%1d", &Map[i][j]);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
Get_Equation(i, j);
Gauss(); printf("Solution:\n");
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
printf("%d", Ans[i][j]);
printf("\n");
}
return 0;
}

  

小游戏 Lights Out (关灯) 的求解 —— 异或方程组的更多相关文章

  1. 高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯

    高斯消元求解异或方程组: 比较不错的一篇文章:http://blog.sina.com.cn/s/blog_51cea4040100g7hl.html cojs.tk  539. 牛棚的灯 ★★☆   ...

  2. 【poj1830-开关问题】高斯消元求解异或方程组

    第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关 ...

  3. 【poj1222-又一道开关问题】高斯消元求解异或方程组

    题意:给出一个5*6的图,每个灯泡有一个初始状态,1表示亮,0表示灭.每对一个灯泡操作时,会影响周围的灯泡改变亮灭,问如何操作可以使得所有灯泡都关掉. 题解: 这题和上一题几乎完全一样..就是要输出解 ...

  4. BZOJ.1923.[SDOI2010]外星千足虫(高斯消元 异或方程组 bitset)

    题目链接 m个方程,n个未知量,求解异或方程组. 复杂度比较高,需要借助bitset压位. 感觉自己以前写的(异或)高斯消元是假的..而且黄学长的写法都不需要回代. //1100kb 324ms #i ...

  5. 自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析

    自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  6. [BZOJ1659][Usaco2006 Mar]Lights Out 关灯

    [BZOJ1659][Usaco2006 Mar]Lights Out 关灯 试题描述 奶牛们喜欢在黑暗中睡觉.每天晚上,他们的牲口棚有L(3<=L<=50)盏灯,他们想让亮着的灯尽可能的 ...

  7. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  8. 拼图小游戏之计算后样式与CSS动画的冲突

    先说结论: 前几天写了几个非常简单的移动端小游戏,其中一个拼图游戏让我郁闷了一段时间.因为要获取每张图片的位置,用`<style>`标签写的样式,直接获取计算后样式再用来交换位置,结果就悲 ...

  9. 推荐10款超级有趣的HTML5小游戏

    HTML5的发展速度比任何人的都想像都要更快.更加强大有效的和专业的解决方案已经被开发......甚至在游戏世界中!这里跟大家分享有10款超级趣味的HTML5游戏,希望大家能够喜欢! Kern Typ ...

随机推荐

  1. 使用solrj操作solr索引库,solr是lucene服务器

    客户端开发 Solrj 客户端开发 Solrj Solr是搭建好的lucene服务器 当然不可能完全满足一般的业务需求 可能 要针对各种的架构和业务调整 这里就需要用到Solrj了 Solrj是Sol ...

  2. careercup-栈与队列 3.4

    3.4 在经典问题汉诺塔中,有3根柱子及N个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子.一开始,所有盘子自底向上从大到小依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面).移动圆盘时有以下限 ...

  3. windows7 'telnet'不是内部或外部命令--转载

    ['telnet'不是内部或外部命令,也不是可运行的程序或批处理文件]当你想用telnet命令时,发现提示这句话怎么办?其实很简单,接下来为大家介绍下如何使用 方法/步骤   一般只有windows7 ...

  4. asp.net网站性能优化2则

    摘要:Web服务器的性能优化有很多资料介绍了,多台主机负载均衡,查询结果的多级缓 存,数据库索引优化等都是常见的优化手段.随着后端优化空间越来越小,现在越来越多 的网站更注重前端性能的优化,就是浏览器 ...

  5. .net缓存应用与分析

    在 ASP.NET 提供的许多特性中,相比 ASP.NET 的所有其他特性,缓存对应用程序的性能具有最大的潜在影响,利用缓存和其他机制,ASP.NET 开发人员可以接受使用开销很大的控件(例如,Dat ...

  6. Android canvas rotate():平移旋转坐标系至任意原点任意角度-------附:android反三角函数小结

    自然状态下,坐标系以屏幕左上角为原点,向右是x正轴,向下是y正轴.现在要使坐标系的原点平移至任一点O(x,y),且旋转a角度,如何实现? 交待下我的问题背景,已知屏幕上有两点p1和p2,构成直线l.我 ...

  7. 在sql2008的实例 中 编写存储过程 读取 版本为sql2005 的实例 中的某个数据库里的数据

     --创建链接服务器 exec sp_addlinkedserver   'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvl ...

  8. 无法加载协定为“ServiceReference1.ReportWsSoap”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分。

    前言 引用websevice时,有时会出现如下错误: 异常详细信息: System.InvalidOperationException: 无法加载协定为“ServiceReference1.Repor ...

  9. [解答]对‘’未定义的引用 collect2: 错误: ld 返回 1

    写的makefile适用于32位,但是放到64位机器上make就有问题. 需要在makefile中gcc -o....的结尾加上-pthread,例如: bloomfilter.o: bloomfil ...

  10. 时间格式nls_date_format的设置

    nls_date_format参数用于设置日期显示格式,设置的方式有多种,不同的方式也会带来不同的结果.参数的设置是有优先级的,日期格式的参数设置也不例外.优先级如下(低到高):初始化参数 < ...