UVa-11464 Even Parity

来源:互联网 发布:淘宝网不能正常打开 编辑:程序博客网 时间:2024/06/07 07:22

题目概述:

给你一个N*N的矩阵,元素为0或1。问你最少把几个0变成1能使每一个元素上下左右(存在哪个加哪个)元素加起来是偶数。如果做不到输出-1;

思路:

N是<=15的。所以可以枚举第一行。然后可以通过第一行来确定剩下的。思路不难,有一个小技巧。利用二进制,巧妙地枚举了所有情况。

比如,n=3.那么,需要枚举2^3=8种情况。分别为:0 0 0,0 0 1,0 1 0,0 1 1 ,1 0 0 ,1 0 1 ,1 1 0,1 1 1.可以发现,恰好是0~7这八个数字的二进制。

然后设置循环变量s,s从0到7.

在设置第i个位置是0还是1的时候,用2^i和s进行&运算,是0就是0,非0就是1。

效果为:

s=0:                        s=1:                  s=2:                 s=3:                   s=4:                 s=5:               s=6:                s=7:

      i=0:0&1=0       i=0:1&1=1       i=0:2&1=0      i=0:3&1=1        i=0:4&1=0      i=0:5&1=1    i=0:6&1=0     i=0:7&1=1

      i=1:0&2=0       i=1:1&2=0       i=1:2&2=2      i=1:3&2=2        i=1:4&2=0      i=1:5&2=0    i=1:6&2=2     i=1:7&2=2

      i=2:0&4=0       i=2:1&4=0       i=2:2&4=0      i=2:3&4=0        i=2:4&4=4      i=2:5&4=4    i=2:6&4=4     i=2:7&4=4

      0 0 0                 1 0 0                0 1 0                1 1 0                  0 0 1               1 0 1              0 1 1              1 1 1

由上表可知其原理。

代码:

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn=15+5;const int INF=1000000000;int n;int before[maxn][maxn],after[maxn][maxn];int check(int s){int i;for (i=0;i<n;i++){memset(after,0,sizeof(after));for (i=0;i<n;i++){if ((1<<i)&s) after[0][i]=1;elseif (before[0][i] == 1) return INF;}int c,r;for (r=1;r<n;r++){for (c=0;c<n;c++){int sum=0;if (r>1) sum+=after[r-2][c];if (c>0) sum+=after[r-1][c-1];if (c<n-1) sum+=after[r-1][c+1];after[r][c]=sum%2;if (before[r][c] == 1 && after[r][c] == 0) return INF;}}int count=0;for (r=0;r<n;++r)for (c=0;c<n;++c)if (before[r][c] != after[r][c]) count++;return count;}}int main(){int kaseNum,kase;scanf("%d",&kaseNum);for (kase=0;kase<kaseNum;++kase){scanf("%d",&n);int i,j;for (i=0;i<n;++i) for (j=0;j<n;++j)scanf("%d",&before[i][j]);int ans=INF;for (i=0;i<(1<<n);++i){ans=min(ans,check(i));}if (ans == INF) ans=-1;printf("Case %d: %d\n",kase+1,ans);}return 0;}

0 0