Uva 11464 - Even Parity

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459

解题报告:题目的意思是,一个nXn 的矩阵,然后每个元素由0或1组成,然后现在要通过将矩阵中的某些0元素变为1来使矩阵的每一个元素的上下左右四个元素(如果存在的话)的值的和为偶数,现在问需要变动的最少的次数是多少?

因为题目的数据量n <= 15,其中一种想法是枚举矩阵的每个元素变还是不变,但是15X15=225,这样时间复杂度将是2^225次方,所以,这样不行。但是我们可以发现如果把第一行的元素都确定下来,那么下面的每一行都可以由上一行推出来,所以,解法就出来了,我们可以每次枚举第一行的元素,然后通过第一行的元素将后面的元素都推出来,这样的话时间复杂度将是2^15,很明显就可以通过测试数据了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 int add_x[4] = {-1,0,1,0};
  7 int add_y[4] = {0,1,0,-1};
  8 int matrix[20][20],temp[20][20];
  9 int changeto(int n,int m)     //一开始傻了,把这个返回值指定为bool型 
 10 {
 11     int f = 0,s = 0;
 12     memset(temp,0,sizeof(temp));
 13     for(int i = 0;i < m;++i)
 14     if(n & (1 << i))
 15     temp[0][i] = 1;
 16     else temp[0][i] = 0;
 17     for(int i = 0;i < m;++i)
 18     {
 19         if(temp[0][i] == 0 && matrix[0][i] == 1)
 20         return -1;
 21         else if(temp[0][i] == 1 && matrix[0][i] == 0)
 22         s++;
 23     }
 24     return s;
 25 }
 26 
 27 int solve(int n)
 28 {
 29     int maxn = 1 << n,ans = 0x7fffffff;
 30     for(int i = 0;i < maxn;++i)
 31     {
 32         int tt = changeto(i,n);
 33         if(tt != -1)        // 枚举第一行,然后其它行就可以由第一行推出 
 34         {
 35             for(int j = 1;j < n;++j)
 36             for(int k = 0;k < n;++k)
 37             temp[j][k] = matrix[j][k];
 38             int t = 0;
 39             for(int j = 0;j < n;++j)
 40             for(int k = 0;k < n;++k)
 41             {
 42                 int sum = 0;
 43                 for(int p = 0;p < 4;++p)    //计算出该点的上下左右四个位置的和 
 44                 {
 45                     int xx = j + add_x[p];
 46                     int yy = k + add_y[p];
 47                     if(xx >= 0 && xx < n && yy >= 0 && yy < n)
 48                     sum += temp[xx][yy];
 49                 }
 50                 if(sum & 1)          //如果四个位置的和为偶数则不用管,如果是奇数则... 
 51                 {
 52                     if(j >= n - 1)         //如果最后一行的出现奇数的话,没有办法了 
 53                     goto loop;
 54                     if(temp[j+1][k] == 1)  //如果下方的是1,不能把1变0,所以也没有办法 
 55                     goto loop;
 56                     else             //剩下的情况就是加起来的和是奇数,但可以将下面的那个数由0变1,其它位置的数一定是固定的 
 57                     {
 58                         temp[j+1][k] = 1;
 59                         t++;
 60                     }
 61                 }
 62             }
 63     //        if(t ==  1 || tt == 1)
 64     //        {
 65     //            printf("i = %d\n",i);
 66     //            for(int j = 0;j < n;++j)
 67     //            for(int k = 0;k < n;++k)
 68     //            printf(k == n-1? "%d\n":"%d ",temp[j][k]);
 69     //        }
 70         //    printf("t = %d tt = %d\n",t,tt);
 71             ans = min(ans,t+tt);   // 别忘记加上第一行变的 
 72         }
 73 loop:       ;
 74     }
 75     return ans > 225? -1:ans;
 76 }
 77 /*int slove(int k,int n)
 78 {
 79     int fir = changeto(k,n);
 80     if(fir == -1)
 81     return 10000;
 82     for(int i = 1;i < n;++i)
 83     
 84     for(int j = 0;j < n;++j)
 85     temp[i][j] = matrix[i][j];
 86     int tot = 0;
 87     for(int i = 0;i < n;++i)
 88     for(int j = 0;j < n;++j)
 89     {
 90         int sum = 0;
 91         for(int p = 0;p < 4;++p)
 92         {
 93             int xx = i + add_x[p];
 94             int yy = j + add_y[p];
 95             if(xx >= 0 && xx < n && yy >= 0 && yy < n)
 96             sum += temp[xx][yy];
 97         }
 98         if(sum & 1)
 99         {
100             if(i >= n - 1 || temp[i+1][j] == 1)
101             return -1;
102             if(temp[i+1][j] == 0)
103             {
104                 temp[i+1][j] = 1;
105                 tot++;
106             }
107         }
108     }
109     return tot+fir;
110 }*/
111 int main()
112 {
113 //    freopen("in.txt","r",stdin);
114     int n,T,kase = 1;
115     scanf("%d",&T);
116     while(T--)
117     {
118         scanf("%d",&n);
119         for(int i = 0;i < n;++i)
120         for(int j = 0;j < n;++j)
121         scanf("%d",&matrix[i][j]);
122         printf("Case %d: %d\n",kase++,solve(n));
123     }
124     return 0;
125 }
View Code

 

posted @ 2014-04-08 22:15  xiaxiaosheng  阅读(222)  评论(0编辑  收藏  举报