POJ 1830 开关问题(高斯消元)题解

思路:乍一看好像和线性代数没什么关系。我们用一个数组B表示第i个位置的灯变了没有,然后假设我用u[i] = 1表示动开关i,mp[i][j] = 1表示动了i之后j也会跟着动,那么第i个开关的最终状态为:u[1]*mp[1][i]^u[2]*mp[2][i]....^u[n]*mp[n][i](或者改为相加 % 2)。显然,前式等于B[i],所以,问题转化为了求u的解个数:MP*U = B。注意MP矩阵的写法。

关于矩阵:

r(A) = r(A,b)           有解

r(A) = r(A,b) = n     有唯一解     (n是未知量的个数,即A的列数)  

r(A) = r(A,b) < n     有无穷多解

参考:开关问题 POJ - 1830 高斯消元

代码:

#include<queue>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
typedef long long ll;
const int maxn = 35 + 10;
const int seed = 131;
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
int A[maxn][maxn], B[maxn], n;
void Gauss(){
    ll R = 0;
    int row = 1;
    for(int i = 1; i <= n && row <= n; i++,row++){
        int max_r = row;
        for(int j = row + 1; j <= n; j++){
            if(A[j][i] > A[row][i]){
                max_r = j;break;
            }
        }
        if(max_r != row){
            for(int k = i; k <= n + 1; k++)
                swap(A[max_r][k], A[row][k]);
        }
        if(A[row][i] == 0){
            row--;
            continue;
        }
        R++;
        for(int j = row + 1; j <= n; j++){
            if(A[j][i]){
                for(int k = i; k <= n + 1; k++)
                    A[j][k] = (A[j][k] - A[row][k] + 2) % 2;
            }
        }
    }
    for(int i = row; i <= n; i++){
        if(A[i][n + 1]){
            printf("Oh,it's impossible~!!\n");
            return;
        }
    }
    R = n - R;
    R = 1 << R;
    printf("%lld\n", R);
}
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", &B[i]);
        for(int i = 1; i <= n; i++){
            int v;
            scanf("%d", &v);
            A[i][n + 1] = B[i] ^ v;
            A[i][i] = 1;
        }
        int u, v;
        while(scanf("%d%d", &u , &v) && u + v){
            A[v][u] = 1;
        }
        Gauss();
    }
    return 0;
}

 

posted @ 2018-09-14 14:25  KirinSB  阅读(197)  评论(0编辑  收藏  举报