poj 1830 开关问题(高斯消元)

来源:互联网 发布:淘宝自己组装iphone 编辑:程序博客网 时间:2024/06/12 19:58
开关问题
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 5106 Accepted: 1876

Description

有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

Input

输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。

Output

如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号

Sample Input

230 0 01 1 11 21 32 12 33 13 20 030 0 01 0 11 22 10 0

Sample Output

4Oh,it's impossible~!!

Hint

第一组数据的说明:
一共以下四种方法:
操作开关1
操作开关2
操作开关3
操作开关1、2、3 (不记顺序)

Source


开关问题,也是用高斯消元法求解。设消元后有r个非0行,且不存在矛盾方程(若存在,则无解),则一共有r个非自由变量,那么自由变量就有n-r个,因为每个自由变量都要0或1两种取值,那么解的个数就是1<<(n - r)。


AC代码:

#include <iostream>#include <cmath>#include <cstdlib>#include <cstring>#include <cstdio>#include <queue>#include <stack>#include <ctime>#include <vector>#include <algorithm>#define ll long long#define L(rt) (rt<<1)#define R(rt)  (rt<<1|1)using namespace std;const int INF = 2000000000;const int maxn = 35;int a[maxn][maxn];int n;void gauss(){    int row = 0, col = 0;    while(row < n && col < n)    {        int id = row;        for(int i = row + 1; i < n; i++)        if(abs(a[i][col]) > abs(a[id][col]))        id = i;        if(a[id][col])        {            for(int i = col; i <= n; i++)            swap(a[id][i], a[row][i]);            for(int i = row + 1; i < n; i++)            if(a[i][col])            {                for(int j = col; j <= n; j++)                a[i][j] ^= a[row][j];            }            row++;        }        col++;    }    for(int i = row; i < n; i++)    if(a[i][n])    {        cout<<"Oh,it's impossible~!!"<<endl;        return;    }    printf("%d\n", 1 << (n - row));}int main(){    int t, x, y;    scanf("%d", &t);    while(t--)    {        memset(a, 0, sizeof(a));        scanf("%d", &n);        for(int i = 0; i < n; i++)        scanf("%d", &a[i][n]);        for(int i = 0; i < n; i++)        {            scanf("%d", &x);            a[i][n] ^= x;            a[i][i] = 1;        }        while(scanf("%d%d", &x, &y), x || y)        {            x--;            y--;            a[y][x] = 1;        }        gauss();    }    return 0;}


0 0
原创粉丝点击