• 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~!!
    ");
                return;
            }
        }
        R = n - R;
        R = 1 << R;
        printf("%lld
    ", 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;
    }
  • 相关阅读:
    arcgis建立拓扑分析(检验矢量图)
    矢量图面层和线层相交得到相交后的线层文件(gis相交)
    关于处理注册表权限无法修改的问题(无法打开主键或注册表项unknown)
    my.cnf配置文件
    keepalived联动mysql
    安装客户端连接软件(zabbix_agentd-filebeat-flume)
    zabbix短信配置说明
    zabbix监控工具添加网络设备Ping
    新买了硬盘,让Linux系统识别硬盘nfs---->改成xfs
    vnc软件使用
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9646241.html
Copyright © 2020-2023  润新知