POJ1830 开关问题

来源:互联网 发布:crossover mac破解 编辑:程序博客网 时间:2024/05/29 09:46

中文题目,就不说题目大意了
解题思路:
由于对于每一个开关最多改变一次,那么对于每一个开关,只有改变与不改变两种操作,设改变操作为1,不改变操作为0,那么对开关的操作可以用一个n维向量x⃗ T=(x1,x2,,xn),其中xi=0或者1
我们需要知道初始状态经过某次操作之后的状态,并拿它与目标状态比较。我们知道,对于开关i,除了对i的操作xi会影响其状态,与其相关联的开关j的操作xj也会影响其状态。显然,只有当开关j影响开关i并且xj=1(即改变开关j),才会使开关i改变。令aij表示开关j是否影响开关i,影响为1,不影响为0,则aijxj表示开关j是否改变开关i,改变为1,不改变为0。若定义aii=1,那么nj=1aijxj就表示开关i被改变的次数。显然,改变次数为奇数,则说明改变初始状态,反之不变。若用向量b⃗ T=(b1,b2,,bn)表示初始状态与目标状态之间的关系,bi表示开关i的目标与初始状态是否一致,1表示不一致,0表示一致,则方程nj=1aijxjbi(mod2)表示将开关i改变为目标状态。由于模运算的性质,我们可以先对线性方程组Ax=b进行初等行变换再对两边取模。由于只需要求可行方案数(即方程解的个数),而并不关心解本身,我们仅仅求得线性方程组系数矩阵与增广矩阵的秩即可。若r(A)<r(A,b)则方程无解(无可行方案),若r(A)=r(A,b)=n则方程有唯一解(有一种方案),若r(A)=r(A,b)<n,由于解向量中自由变元仅有两种取值(01),可行方案数为2r(A,b)r(A)

#include<iostream>#include<cmath>#include<algorithm>#include<cstring>using namespace std;int ab[50][50], st[50], en[50];inline int gauss(int n){    int i = 0, j = 0, k;    while (j < n)    {        int id = i;        for (k = i + 1; k < n; k++)            if (abs(ab[k][j]) > abs(ab[id][j]))                id = k;        if (id != i)        {            for (k = j; k <= n; k++)                swap(ab[i][k], ab[id][k]);        }        if (ab[i][j] == 0) { j++; continue; }        for (k = i + 1; k < n; k++)        {            if (ab[k][j] == 0) continue;            for (int l = j; l <= n; l++)                ab[k][l] = ab[k][l] ^ ab[i][l];        }        i++, j++;    }    for (int k = i; k < n; k++)         if (ab[k][n] != 0) return -1;    return 1 << (n - i);}int main(){    int T;    cin >> T;    while (T--)    {        int n;        cin >> n;        for (int i = 0; i < n; i++) cin >> st[i];        for (int i = 0; i < n; i++) cin >> en[i];        memset(ab, 0, sizeof(ab));        for (int i = 0; i < n; i++)            ab[i][i] = 1, ab[i][n] = st[i] ^ en[i];        int I, J;        cin >> I >> J;        while (I)        {            ab[J - 1][I - 1] = 1;            cin >> I >> J;        }        int ans = gauss(n);        if (ans == -1)  cout << "Oh,it's impossible~!!\n";        else cout << ans << endl;    }    return 0;}
0 0
原创粉丝点击