| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2569 人关注过本帖
标题:为什么时间超时
只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
呵呵,找到了。
先分析一下游戏规则,看看我们从中能得到些什么信息。
 N*N灯阵,初始状态任意,每盏灯开关可控制该灯及所有相邻灯,即本灯开关开或合一次使本灯及相邻灯的开关状态取反。
 给出算法使所有灯全亮开关次数最少(或不可能)。

由上面的规则可以看出
 1、灯阵中每盏灯的状态只有两种(亮或者灭),为便于接下来的讨论我们把灯的状态参数化,规定亮为1,灭为0。

2、一次可以操作一盏灯。

3、对某一盏灯的操作只有一种,即对该灯的状态取反。如果该灯原来为1,那么操作结果使它为0;如果该灯为0,那么操作结果使它为1。

4、由上一信息可以知道:对一盏灯操作奇数次结果均为使灯状态改变,操作偶数次结果均不改变灯的状态。
 这些说明,要改变某盏灯的状态最多只需对它操作1次(1次以上的操作是多余的)。

5、设灯阵为LM(LM 是“Lights Matrix”的缩写,这只是我个人的喜好,没什么特别的意思,大家可以随意取名:))LM具有N * N个元素或者叫灯,它的某一状态为LMA,另一状态为LMB(LMA不等于LMB,即是说LMA和LMB中至少存在1个对应位置的灯的状态是不同的)。从LMA变换到LMB需要操作K盏灯,设这K盏灯分别为L1、L2、...、LK(Li表示LM中的某一个元素或者说位置,即某个LM(a,b))。
 那么,只要操作了这K盏灯就能从LMA变换到LMB,与这K盏灯的操作顺序无关(即假设需要操作L1和L2两盏灯,那么先操作L1再操作L2与先操作L2再操作L1的结果是一样的)。关于这一结论的证明并不难,我就不赘述了。由这一结论也可以知道K盏灯中不会有两盏相同的灯。
 为了下面讨论方便,我们设从LMA 到 LMB 的操作为T(取Turn的意思)。
 上面的描述可以函数化为 T(LMA) = LMB。不同的操作将用T1、T2或TA、TB等表示。两个相同的操作是指它们操作的灯的数量及位置都是相同的。(例如:T1操作LM中L1、L2、L3这三盏灯,如果T2操作的也是这三盏灯那我们说T1=T2,如果T2中操作了其它灯或者只是T1中操作的部分灯,那T1 != T2)在下面的讨论中相同操作名的操作将表示相同的操作。

6、设LM中灯的状态全为0的灯阵状态为LM0,LM中灯的状态全为1的灯阵状态为LMZ。在本文中LM0和LMZ将作为特定灯阵,其它灯阵状态作为变量将用LM1、LM2、LMA、LMB等等泛指。
 作这些定义是为了描述下面这样一个问题:
 设T(LMA) = LMB,是否存在一个LMC,使得T(LM0) = LMC ?如果存在LMC又是什么样的?

答案是肯定的。如果存在T(LMA) = LMB ,那么一定存在LMC,且LMC = LMA ^ LMB(“^”表示异或)
 即是说T(LM0) = LMA ^ LMB。
 这个证明也不难,留给大家自己思考了。

由此,原题要求由某一状态LMA变换到LMZ就映射成由LM0变换到LMA ^ LMZ。即由T(LMA) = LMZ => T(LM0) = LMA ^ LMZ。

分析到这里也差不多了,该着手由我们分析的结果来解决这个问题了。

首先来将上面提到的那些抽象概念具体化。
 LM是一个矩阵,可以用一个二维数组表示。LM(i,j)表示LM中第i行第j列的灯。
 T要操作的灯我们用L来表示。L也是一个矩阵。L(i,j)表示LM中第i行第j列的灯的操作。L(i,j)为1表示要操作LM中第i行第j列的灯。L(i,j)为0表示不操作。
 设T(LM0) = LMA。那么根据题中点灯规则可以得出

LMA(i,j) = L(i-1,j) ^ L(i,j-1) ^ L(i,j) ^ L(i,j+1) ^ L(i+1,j)

其中的i-1,i+1,j-1,j+1可能超出数组的界限。对于超出界限的L(a,b)我们视做0。

这个运算过程也就是T操作的过程了。我们想要的结果也就是这个T的L了。
 这么说还是太抽象。我举个2X2的例子说明一下。
 

 LMA = [ a00, a01,
         a10, a11]
 设一个列向量Y,

 Y = [ a00,
       a01,
       a10,
       a11]

能实现将LM0转换成LMA的操作中的L为

 L = [ b00, b01,
       b10, b11]

设一个列向量X,

 X = [ b00,
       b01,
       b10,
       b11]

那么根据操作过程我们得到下面的方程

 b00 ^ b01 ^ b10 = a00
 b00 ^ b01 ^ b11 = a01
 b00 ^ b10 ^ b11 = a10
 b01 ^ b10 ^ b11 = a11

其中a00,a01,a10,a11是已知数,b00,b01,b10,b11是代求的未知数。
 解这个方程组可以求得

 b00 = a00 ^ a01 ^ a10
 b01 = a00 ^ a01 ^ a11
 b10 = a00 ^ a10 ^ a11
 b11 = a01 ^ a10 ^ a11

这是手工解法,现在讨论怎么用计算机求解

由于逻辑运算中的异或在很多方面与代数运算中的加法很相似,所以这里我们可以借鉴代数中线性方程组的解法来解这个逻辑方程组。

我们重新规范一下上面的方程组

a00 = b00 ^ b01 ^ b10,这个方程里只出现了三个未知数,我们将b11也补进去。

a00 = 1*b00 ^ 1*b01 ^ 1*b10 ^ 0*b11。因为0*b11=0,而0异或其它值还是其它值,这样的改写我想大家没异议吧。
 同理
 a00 = 1*b00 ^ 1*b01 ^ 1*b10 ^ 0*b11
 a01 = 1*b00 ^ 1*b01 ^ 0*b10 ^ 1*b11
 a10 = 1*b00 ^ 0*b01 ^ 1*b10 ^ 1*b11
 a11 = 0*b00 ^ 1*b01 ^ 1*b10 ^ 1*b11

这样我们得到方程的系数矩阵

 1 1 1 0
 1 1 0 1
 1 0 1 1
 0 1 1 1

设这个系数矩阵为A

那么上面的方程可以表示成矩阵形式

AX = Y

之后对于矩阵的运算完全可以用于上式的运算,只不过原来的加法现在要换成异或。比如,初等行变换中“某一行所有元素的K倍加到另一行的元素上去”应换成“某一行所有元素异或到另一行的元素上去”。而且异或的运算变量是布尔型的,所以那个K倍也就用不上了(K倍的真还是真,K倍的假还是假)。


用高斯消去法可以很方便的解这个方程组。更高阶的游戏也可以同理解出来。对于N*N的游戏,其中未知量将有N的平方个,游戏要的结果就是解中为1的量对应的灯。操作解中为1的灯就会得到结果。
当系数矩阵A为非奇异矩阵,或者说是满秩矩阵时,方程组有唯一解。
 当A为降秩矩阵时,方程组有多组或没有解。
 具体情况是,当方程的增广矩阵经过初等行变换后,A中元素全为0的某行对应的Y的元素为0时方程组有多组解,对应的Y的元素不为0时方程组无解。
 这与代数线性方程组的情况是一样的。只不过因为代数中变量的定义域是实数范围,一但方程组的解不唯一它将有无穷多组解。但我们这样逻辑线性议程组的定义域只有0和1,解不唯一时其解的总数是有限的。当有n个自由未知量时,方程将有n的2次方组解。
 



重剑无锋,大巧不工
2012-01-05 18:11
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 11楼 beyondyf
找到了,poj1222就是这个

矩阵这学期刚学,总算知道系统理解了高斯消元的原理,还有就是fib数列的logn算法,不过,貌似我们专业学得蛮浅的,不知有没有必要再自己加深学一下?
2012-01-05 23:25
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
真够有心的
我的矩阵知识也只限于上学时那本薄薄的工科《线性代数》。矩阵是一种比较新的数学工具(相对于微积分而言),上世纪由于在量子学中的应用脱颖而出,多学一些肯定不错的。尤其你还在上学,相对比较有时间做你想做的事情,喜欢就多学一点呗。

重剑无锋,大巧不工
2012-01-05 23:47
快速回复:为什么时间超时
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.013699 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved