poj1830 开关问题(gauss)

来源:互联网 发布:ubuntu 14.04安装qq 编辑:程序博客网 时间:2024/06/05 14:49

poj上的中文题面,大家一定要亲眼见证一下

分析:
这道题和poj1222大同小异
还是异或方程求解
唯一不同的就是,需要计算方案数
这就和那些不确定的元素有关了
每个不定元都有两种选择:开或关
所以方案数就是
2^(不定元个数)

tip

怎么确定有没有解呢

for (int i=n;i>=1;i--)    if (a[i][n+1]!=0&&a[i][i]==0)        return 0;

不要忘了now++

注意

题目描述中:
每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化
也就是说第I决定第J个,所以a[J][I]=1
所以在列方程的时候,一定要找好对应关系
这再一次说明了那条真理

样例都是逗你玩的

//这里写代码片#include<cstdio>#include<iostream>#include<cstring>using namespace std;int cnt,n;int mp1[35],mp2[35];int a[35][35];int gauss(){    cnt=0;    int now=1,to;    for (int i=1;i<=n;i++)    {        for (to=now;to<=n;to++)            if (a[to][i]) break;        if (to>n)    //不定元         {            cnt++;            now++;            continue;        }        if (to!=now)            for (int j=1;j<=n+1;j++)                swap(a[to][j],a[now][j]);        for (int j=1;j<=n;j++)            if (j!=now&&a[j][i])                for (int k=1;k<=n+1;k++)                    a[j][k]^=a[now][k];        now++;    }    for (int i=n;i>=1;i--)        if (a[i][n+1]!=0&&a[i][i]==0)            return 0;    return 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",&mp1[i]);        for (int i=1;i<=n;i++) scanf("%d",&mp2[i]);        int x,y;        scanf("%d%d",&x,&y);        while (x&&y)        {            a[y][x]=1;            scanf("%d%d",&x,&y);        }        for (int i=1;i<=n;i++)        {            a[i][i]=1;            a[i][n+1]=mp1[i]^mp2[i];        }        if (gauss())        {            printf("%d\n",(1<<cnt));        }        else printf("Oh,it's impossible~!!\n");    }    return 0;}
原创粉丝点击