POJ 3185 The Water Bowls(高斯消元-枚举变元个数)

题目链接:http://poj.org/problem?id=3185

题意:20盏灯排成一排。操作第i盏灯的时候,i-1和i+1盏灯的状态均会改变。给定初始状态,问最少操作多少盏灯使得所有灯的状态最后均为0.

思路:高斯消元,记录变元个数,枚举变元。

 

int a[N][N],ans[N];

vector<int> b;



int Gauss()

{

    b.clear();

    int i,j=1,k,t;

    for(i=1;i<=20;i++)

    {

        for(k=j;k<=20;k++) if(a[k][i]) break;

        if(k>20)

        {

            b.pb(i);

            continue;

        }

        for(t=1;t<=21;t++) swap(a[k][t],a[j][t]);

        for(t=1;t<=20;t++) if(t!=j&&a[t][i])

        {

            for(k=1;k<=21;k++) a[t][k]^=a[j][k];

        }

        j++;

    }

    for(i=j;i<=20;i++) if(a[i][21]) return -1;

    if(j<=20) return 21-j;

    for(i=1;i<=20;i++) ans[i]=a[i][21];

    return 0;

}



int main()

{

    int num=0;

    int i;

    FOR1(i,20)

    {

        RD(a[i][21]);

        a[i][i]=1;

        if(i>1) a[i-1][i]=1;

        if(i<20) a[i+1][i]=1;

    }

    int t=Gauss();

    if(t==0)

    {

        int sum=0;

        FOR1(i,20) sum+=ans[i];

        PR(sum);

        return 0;

    }

    int sum=INF,st,j,k;

    FOR0(st,(1<<t))

    {

        FOR0(i,t) ans[b[i]]=(st>>i)&1;

        for(i=20-t;i>=1;i--)

        {

            for(j=i;j<=20;j++) if(a[i][j]) break;

            ans[j]=a[i][21];

            for(k=j+1;k<=20;k++) if(a[i][k]) ans[j]^=ans[k];

        }

        int temp=0;

        FOR1(i,20) temp+=ans[i];

        upMin(sum,temp);

    }

    PR(sum);

}

  

 

你可能感兴趣的:(water)