HDU3364 Lanterns【高斯消元法】

来源:互联网 发布:月度m2数据 编辑:程序博客网 时间:2024/05/29 15:59

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3364


题目大意:

有 N 盏灯,M 个开关,每个开关可以控制多盏灯,每盏灯可以被多盏开关控制。

始每盏灯都是开闭状态,给定每盏灯的最终状态,问有多少种方案可以到达。


解题思路:

对于每一盏灯,可以列出一个方程,这样就可以列出 N 个方程,有 M 个未知量。

而构成一个 N*M 的矩阵,对应每盏灯的最终状态。构建一个增广矩阵,用高斯消元

法求解自由变元个数 Ans。因为开关只有开、关两种状态,所以答案为 2^Ans。


AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int MAXN = 55;const int INF = 0xfffff0;int Equ,Var;int A[MAXN][MAXN],B[MAXN][MAXN];int X[MAXN];bool FreeX[MAXN];int FreeNum;int GCD(int a,int b){    if(b == 0)        return a;    return GCD(b,a%b);}int LCM(int a,int b){    return a / GCD(a,b) * b;}int Gauss(){    int i,j,k;    int MaxRow;    int col = 0;    int Lcm;    int ta,tb;    int temp;    int FreeXNum;    int FreeIndex;    for(i = 0; i < Var; ++i)    {        X[i] = 0;        FreeX[i] = true;    }    for(k = 0; k < Equ && col < Var; ++k,++col)    {        MaxRow = k;        for(i = k+1; i < Equ; ++i)        {            if(abs(A[i][col]) > abs(A[MaxRow][col]))                MaxRow = i;        }        if(MaxRow != k)        {            for(j = k; j < Var+1; ++j)                swap(A[k][j],A[MaxRow][j]);        }        if(A[k][col] == 0)        {            k--;            continue;        }        for(i = k+1; i < Equ; ++i)        {            if(A[i][col])            {                Lcm = LCM(abs(A[i][col]),abs(A[k][col]));                ta = Lcm / abs(A[i][col]);                tb = Lcm / abs(A[k][col]);                if(A[i][col] * A[k][col] < 0)                    tb = -tb;                for(j = col; j < Var+1; ++j)                {                    A[i][j] = (A[i][j]*ta%2 - A[k][j]*tb%2 + 2) % 2;                }            }        }    }    for(i = k; i < Equ; ++i)    {        if(A[i][col])            return -1;    }    if(k < Var)        return Var - k;    return 0;}int main(){    int T,t,d,kase = 0;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&Equ,&Var);        memset(A,0,sizeof(A));        memset(B,0,sizeof(B));        memset(X,0,sizeof(X));        for(int i = 0; i < Var; ++i)        {            scanf("%d",&t);            while(t--)            {                scanf("%d",&d);                B[d-1][i] = 1;            }        }        printf("Case %d:\n",++kase);        scanf("%d",&t);        while(t--)        {            memcpy(A,B,sizeof(B));            for(int i = 0; i < Equ; ++i)                scanf("%d",&A[i][Var]);            int Ans = Gauss();            if(Ans == -1)                printf("0\n");            else                printf("%I64d\n",1LL << (Ans));        }    }    return 0;}

0 0
原创粉丝点击