题目链接:http://poj.org/problem?id=1830
题目描述:中文题,POJ上的描述是:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。( 不计开关操作的顺序)
思路:在做另一道类似的题目时跑来先做这道更好理解的题题了。第一次做出高斯消元这类题目,这两天抽空看了网上很多高斯消元相关介绍,也算是对其有了较浅的认识,今天打算再做三道这方面的题目就睡觉。这道题给了初末时刻所有开关的状态,分别设S[i] 和 E[i] 分别为开关i的初末状态,若E[i] ^ S[i] == 1则说明开关i的状态发生了变化。设A[i][j] == 1表示开关j可以控制开关i,注意A[i][i] == 1(每个开关都可以控制自身),X[i]表示是否打开或关闭开关i。则E[i] ^ S[i] == A[i][1] * X[1] ^ A[i][2] * X[2] ^ ... ^ A[i][n] * X[n],A[i][j] * X[j]表示只有第j个开关能控制第i个开关并且对第j个开关进行状态修改时第i个开关的状态才会发生变化,所有控制i灯的灯异或就是i等最后的状态。
这样就列如下等式(每个元素的值只有可能为0或1):
E[1] ^ S[1] = A[1][1] * X[1] ^ A[1][2] * X[2] ^ ... ^ A[1][n] * X[n]
E[2] ^ S[2] = A[2][1] * X[1] ^ A[2][2] * X[2] ^ ... ^ A[2][n] * X[n]
......
E[n] ^ S[n] = A[n][1] * X[1] ^ A[n][2] * X[2] ^ ... ^ A[n][n] * X[n]
即:E^S = A^X
这样就变成了求解线性方程组解的个数的问题,这样就可以用高斯消元做了。具体步骤是首先在增广矩阵中找到第一个第一列非0的行,将其与第一行交换,然后将其他行进行消元(本题就是将其他行与第一行对应元素进行异或操作),看下一列(若第一列元素全为0,则直接处理下一列)。直到将增广矩阵的倒数第二列也处理完后,如果有解,此时系数矩阵(增广矩阵最后一列)应该全为0,否则则无解。第一次做有关高斯消元的题目,大一时现代也没好好学,有些地方可能说的不好或不恰当,欢迎指正或赐教。
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include