开关问题 POJ 1830(高斯消元求解的个数)
2017-08-17 23:45
204 查看
题目链接: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]
* X
,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]
* X
E[2] ^ S[2] = A[2][1] * X[1] ^ A[2][2] * X[2] ^ ... ^ A[2]
* X
......
E
^ S
= A
[1] * X[1] ^ A
[2] * X[2] ^ ... ^ A
* X
即:E^S = A^X
这样就变成了求解线性方程组解的个数的问题,这样就可以用高斯消元做了。具体步骤是首先在增广矩阵中找到第一个第一列非0的行,将其与第一行交换,然后将其他行进行消元(本题就是将其他行与第一行对应元素进行异或操作),看下一列(若第一列元素全为0,则直接处理下一列)。直到将增广矩阵的倒数第二列也处理完后,如果有解,此时系数矩阵(增广矩阵最后一列)应该全为0,否则则无解。第一次做有关高斯消元的题目,大一时现代也没好好学,有些地方可能说的不好或不恰当,欢迎指正或赐教。
代码如下:
题目描述:中文题,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]
* X
,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]
* X
E[2] ^ S[2] = A[2][1] * X[1] ^ A[2][2] * X[2] ^ ... ^ A[2]
* X
......
E
^ S
= A
[1] * X[1] ^ A
[2] * X[2] ^ ... ^ A
* X
即:E^S = A^X
这样就变成了求解线性方程组解的个数的问题,这样就可以用高斯消元做了。具体步骤是首先在增广矩阵中找到第一个第一列非0的行,将其与第一行交换,然后将其他行进行消元(本题就是将其他行与第一行对应元素进行异或操作),看下一列(若第一列元素全为0,则直接处理下一列)。直到将增广矩阵的倒数第二列也处理完后,如果有解,此时系数矩阵(增广矩阵最后一列)应该全为0,否则则无解。第一次做有关高斯消元的题目,大一时现代也没好好学,有些地方可能说的不好或不恰当,欢迎指正或赐教。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<cstdlib> #include<sstream> #include<deque> #include<stack> #include<set> #include<map> using namespace std; typedef long long ll; typedef unsigned long long ull; const double eps = 1e-6; const int maxn = 29 + 10; const int mod = 10; const int dx[] = {1, -1, 0, 0}; const int dy[] = {0, 0, -1, 1}; const int Dis[] = {-1, 1, -5, 5}; const int inf = 0x3f3f3f3f; int n, m, k; int s[maxn], e[maxn]; int a[maxn][maxn];//a[i][j]表示第j个开关对第i个开关的控制情况,为1则说明j控制i,为0则不控制 int Gauss(){ int i, j, r, x, y; for(i = 1, j = 1; i <= n && j <= n; ++j){ r = i; while(r <= n && !a[r][j]) ++r;//找到第j列第一个非零元素所在行 if(a[r][j]){//若该列存在非零元素 swap(a[i], a[r]);//将非零元素所在的行交换到当前行第i行 for(x = 1; x <= n; ++x){//除当前行第i行外,若其他n-1行中有第j列元素非零的行,利用第i行对该行进行消元(此题中即进行异或操作) if(x != i && a[x][j]){ for(y = i; y <= n + 1; ++y) a[x][y] ^= a[i][y]; } } ++i;//继续处理下一行 } } for(x = i; x <= n; ++x){//若最后增广列没有全部变成0,则说明该增广矩阵无解 if(a[x][n + 1]) return -1; } return 1 << (n - i + 1);//自由变量个数为n - i + 1个,解的个数就是1<<(n - i - 1) } int main(){ int t; scanf("%d", &t); while(t--){ scanf("%d", &n); memset(a, 0, sizeof a); for(int i = 1; i <= n; ++i) scanf("%d", &s[i]);//开关的初始状态 for(int i = 1; i <= n; ++i){ scanf("%d", &e[i]);//开关的末状态 a[i][i] = 1;//每个开关可以控制其自身 a[i][n + 1] = s[i] ^ e[i]; } int u, v; while(~scanf("%d%d", &u, &v) && u && v){ a[v][u] = 1; } int ans = Gauss(); if(ans == -1) printf("Oh,it's impossible~!!\n"); else printf("%d\n", ans); } return 0; } /* 2 3 0 0 0 1 1 1 1 2 1 3 2 1 2 3 3 1 3 2 0 0 3 0 0 0 1 0 1 1 2 2 1 0 0 */
相关文章推荐
- POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题
- poj 1830 开关问题 【高斯消元 求解自由变元数目】
- POJ 1830 开关问题 (高斯消元)
- poj 1830 开关问题 高斯消元
- poj 1830 开关问题 (高斯消元)
- [省选前题目整理][POJ 1830]开关问题(XOR方程组高斯消元)
- [高斯消元] poj 1830 开关问题
- POJ 1830 开关问题(高斯消元)
- poj 1830 开关问题(线性方程组,高斯消元)
- POJ 1830 开关问题(高斯消元)
- poj 1830 开关问题(高斯消元)
- 【POJ 1830】 开关问题 (高斯消元)
- poj 1830 开关问题(高斯消元(开关问题))
- POJ 1222 & 1681 & 1830 & 3185 开关灯问题 (高斯消元 & 异或方程组)
- 【高斯消元】【poj 1830】开关问题
- poj 1830 开关问题 1830 高斯消元
- POJ 1222 & 1681 & 1830 & 3185 开关灯问题 (高斯消元 & 异或方程组)
- POJ-1830 开关问题 高斯消元
- poj 1830 开关问题 (高斯消元)
- poj 1830 开关问题 高斯消元