• POJ 1830 高斯消元


    开关问题
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 9883   Accepted: 3971

    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

    2
    3
    0 0 0
    1 1 1
    1 2
    1 3
    2 1
    2 3
    3 1
    3 2
    0 0
    3
    0 0 0
    1 0 1
    1 2
    2 1
    0 0
    

    Sample Output

    4
    Oh,it's impossible~!!
    

     

    思路:
    高斯消元:a*X=b
    若第x个开关跟第y个相连,则系数矩阵中a[y][x]=1,初始化中a[i][i]=1,初始情况和最后情况亦或一下就是我们的b矩阵。
     
    代码:
     1 //#include"bits/stdc++.h"
     2 #include<sstream>
     3 #include<iomanip>
     4 #include"cstdio"
     5 #include"map"
     6 #include"set"
     7 #include"cmath"
     8 #include"queue"
     9 #include"vector"
    10 #include"string"
    11 #include"cstring"
    12 #include"time.h"
    13 #include"iostream"
    14 #include"stdlib.h"
    15 #include"algorithm"
    16 #define db double
    17 #define ll long long
    18 #define vec vector<ll>
    19 #define mt  vector<vec>
    20 #define ci(x) scanf("%d",&x)
    21 #define cd(x) scanf("%lf",&x)
    22 #define cl(x) scanf("%lld",&x)
    23 #define pi(x) printf("%d
    ",x)
    24 #define pd(x) printf("%f
    ",x)
    25 #define pl(x) printf("%lld
    ",x)
    26 //#define rep(i, x, y) for(int i=x;i<=y;i++)
    27 #define rep(i, n) for(int i=0;i<n;i++)
    28 const int N   = 1e2+ 5;
    29 //const int mod = 1e9 + 7;
    30 //const int MOD = mod - 1;
    31 const int inf = 0x3f3f3f3f;
    32 const db  PI  = acos(-1.0);
    33 const db  eps = 1e-10;
    34 using namespace std;
    35 int equ,var;//equ个方程,var个变量,增广矩阵行数为equ,列数为var+1,分别为0到var
    36 int a[N][N];//增广矩阵
    37 int x[N];//存储自由变元
    38 int f_x[N];
    39 int free_x;//自由变元个数
    40 void swap(int &x,int &y){
    41     int t;
    42     t=x,x=y,y=t;
    43 }
    44 int Gauss()
    45 {
    46     int ma_r,col,k;
    47     free_x=0;
    48     for(k=0,col=0;k<equ&&col<var;k++,col++){
    49         ma_r = k;
    50         for (int i = k + 1; i < equ; i++) if (abs(a[i][col] > abs(a[ma_r][col]))) ma_r = i;//取系数最大的一行
    51         if (!a[ma_r][col]) {
    52             k--;
    53             f_x[free_x++] = col;
    54             continue;
    55         }
    56         if (ma_r != k)
    57             for (int j = col; j < var + 1; j++) swap(a[k][j], a[ma_r][j]);//与当前行交换
    58 
    59         for (int i = k + 1; i < equ; i++)
    60             if (a[i][col] != 0)
    61                 for (int j = col; j < var + 1; j++) a[i][j] ^= a[k][j];//消除其他行第col列的变量
    62     }
    63     for(int i=k;i<equ;i++) if(a[i][col]!=0) return -1;//没被消除则无解
    64 
    65     if(k<var) return var-k;//自由变元个数
    66     //唯一解,回代
    67     for(int i=var-1;i>=0;i--){
    68         x[i]=a[i][var];
    69         for(int j=i+1;j<var;j++) x[i]^=(a[i][j]&&x[j]);//自下而上
    70     }
    71     return 0;
    72 }
    73 int n;
    74 int main()
    75 {
    76     int t;
    77     ci(t);
    78     for(int I=1;I<=t;I++){
    79         memset(a,0,sizeof(a));
    80         ci(n);
    81         int x, y;
    82         for (int i = 0; i < n; i++) ci(a[i][n]);
    83         for (int i = 0; i < n; i++) ci(x), a[i][n] ^= x;
    84         for (int i = 0; i < n; i++) a[i][i] = 1;
    85         while (scanf("%d%d", &x, &y), x + y) a[y-1][x-1] = 1;
    86         equ = n, var = n;
    87         int ans = Gauss();
    88         if(ans == -1) puts("Oh,it's impossible~!!");
    89         else
    90             pl(1ll << ans);
    91     }
    92     return 0;
    93 }
     
  • 相关阅读:
    藏!Java编程技巧之单元测试用例编写流程 原创 常意 阿里技术 2021-05-12
    时间,遵循rfc3339标准格式 unix时间戳
    微软面试题: LeetCode 240. 搜索二维矩阵 II 出现次数:3
    微软面试题: LeetCode 69. x 的平方根 出现次数:3
    微软面试题: LeetCode 138. 复制带随机指针的链表 出现次数:3
    微软面试题: LeetCode 384. 打乱数组 出现次数:3
    微软面试题: LeetCode 207. 课程表 出现次数:3
    微软面试题: LeetCode 98. 验证二叉搜索树 出现次数:3
    CF1537E2 Erase and Extend (Hard Version) 题解
    洛谷 P4332 [SHOI2014]三叉神经树 题解
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/8911590.html
Copyright © 2020-2023  润新知