• HDU 3364 高斯消元


    Lanterns

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 2396    Accepted Submission(s): 937


    Problem Description
    Alice has received a beautiful present from Bob. The present contains n lanterns and m switches. Each switch controls some lanterns and pushing the switch will change the state of all lanterns it controls from off to on or from on to off. A lantern may be controlled by many switches. At the beginning, all the lanterns are off. 

    Alice wants to change the state of the lanterns to some specific configurations and she knows that pushing a switch more than once is pointless. Help Alice to find out the number of ways she can achieve the goal. Two ways are different if and only if the sets (including the empty set) of the switches been pushed are different.
     
    Input
    The first line contains an integer T (T<=5) indicating the number of test cases.
    The first line of each test case contains an integer n (1<=n<=50) and m (1<=m<=50).
    Then m lines follow. Each line contains an integer k (k<=n) indicating the number of lanterns this switch controls.
    Then k integers follow between 1 and n inclusive indicating the lantern controlled by this switch.
    The next line contains an integer Q (1<=Q<=1000) represent the number of queries of this test case.
    Q lines follows. Each line contains n integers and the i-th integer indicating that the state (1 for on and 0 for off) of the i-th lantern of this query.
     
    Output
    For each test case, print the case number in the first line. Then output one line containing the answer for each query.
    Please follow the format of the sample output.
     
    Sample Input
    2 3 2 2 1 2 2 1 3 2 0 1 1 1 1 1 3 3 0 0 0 2 0 0 0 1 0 0
     
    Sample Output
    Case 1: 1 0 Case 2: 8 0
     
    Source

     题意:

    就是给了 n 个灯 m 个开关,每个开关能够控制很多灯,当然了每个灯也可以由多种开关控制。现在给了你每个开关能够控制的灯的标号,

    然后给你一个最终状态,让你求的是能够达到这个最终状态的方法数(初始状态都是关着的,开着是 1,关着是 0).

    思路:

    解题思路:

    有 n 个灯也就意味着我们要列 n 个方程, m 个开关就是 m 个未知数,首先通过输入的开关控制的灯可以确定初始的 a(系数矩阵),注意的是 a 矩阵的列和行的变化。

    然后通过给定的最终状态来确定 a∗x = b 的 列矩阵 b,然后就正常高消就行了,还有需要注意的一点是:它给定的 Q 个询问的时候,我们要提前将 a 矩阵保存

    因为高消之后 a 矩阵就变了,所以我们就将 a 矩阵保存。

     代码:

      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 b[N][N];
     74 int n,m;
     75 int main()
     76 {
     77     int t;
     78     ci(t);
     79     for(int I=1;I<=t;I++)
     80     {
     81         ci(n),ci(m);
     82         memset(a,0, sizeof(a));
     83         for(int i=0;i<m;i++){
     84             int k,c;
     85             ci(k);
     86             for(int j=0;j<k;j++) ci(c),a[c-1][i]=1;
     87         }
     88         equ=n,var=m;
     89         for(int i=0;i<equ;i++){
     90             for(int j=0;j<var;j++){
     91                 b[i][j]=a[i][j];
     92             }
     93         }
     94         int q;
     95         ci(q);
     96         printf("Case %d:
    ",I);
     97         while(q--)
     98         {
     99             for(int i=0;i<equ;i++)
    100                 for(int j=0;j<var;j++)
    101                     a[i][j]=b[i][j];
    102             for(int i=0;i<n;i++) ci(a[i][var]);
    103             int ans=Gauss();
    104             if(ans==-1) puts("0");
    105             else pl(1ll<<ans);
    106         }
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    socket编程中最常用的几个数据类型和转换函数
    windows下给QT可执行文件(exe)一个图标
    fseek函数与ftell函数使用例程
    LINUX C例程1:sscanf的用法
    Linux进程控制——exec函数族
    Linux查看文件编码格式及文件编码转换
    oracle易忘函数用法(1)
    Oracle VARRAY的实际应用简介
    oracle 存储过程的基本语法 及注意事项
    何将ext中的FormPanel中,所有组件都居中放置?
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/8911244.html
Copyright © 2020-2023  润新知