UVa 11464

解题报告:题目大意有一个N×N的矩阵,矩阵中的元素只有1或0,如果说对于一个矩阵,它的所有的点的上下左右的点的和是偶数,则称这个矩阵为偶数矩阵,现在给你一个任意的矩阵,要求的是如果要把这个矩阵变成偶数矩阵的话,最少需要将多少个点由1变成0,若不存在话,输出-1.(N<=15)

这题如果枚举每个点的情况的话,虽然N最大只有15,但这样枚举的计算量依然非常大。但是我们可以发现,如果知道第一行的每一个点是什么样的,完全可以计算出下面的N-1行的每一个点。这样我们只要枚举第一行的每一个点的情况,这样的话时间复杂度就降为2^15,很明显快多了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int xxx[5]={0,-1,0,1,0};
 6 int yyy[5]={0,0,1,0,-1};
 7 const int MAX=0xffffff;
 8 int n,mep[16][16];
 9 int check(int s) {
10     int mp[16],map[16][16],tot=0;
11     memset(mp,0,sizeof(mp));
12     memset(map,0,sizeof(map));
13     for(int i=0;i<n;++i)
14     if(s & (1<<i)) {
15         if(mep[1][i+1]==0)
16         tot++;
17         mp[i+1]=1;
18     }
19     else if(mep[1][i+1]==1)
20     return MAX;
21     for(int i=1;i<=n;++i)
22     map[1][i]=mp[i];
23     for(int i=2;i<=n;++i)
24     for(int j=1;j<=n;++j)
25     map[i][j]=mep[i][j];
26 
27     for(int i=1;i<=n;++i)
28     for(int j=1;j<=n;++j) {
29         int sum=0;
30         for(int k=1;k<=4;++k) {
31             int xx=i+xxx[k];
32             int yy=j+yyy[k];
33             if(xx<=0||yy<=0||xx>n||yy>n)
34             continue;
35             sum+=map[xx][yy];
36         }
37         if(sum%2) {
38             if(i!=n&&map[i+1][j]==0) {
39                 map[i+1][j]=1;
40                 tot++;
41             }
42             else return MAX;
43         }
44     }
45     return tot;
46 }
47             
48 int main( ) {
49     int T;
50     scanf("%d",&T);
51     for(int l=1;l<=T;++l) {
52         scanf("%d",&n);
53         for(int i=1;i<=n;++i)
54         for(int j=1;j<=n;++j)
55         scanf("%d",&mep[i][j]);
56         int ans=MAX;
57         for(int s = 0;s < (1 << n ) ; ++s) //(1 << n )注意这个范围不能大也不能小 
58         ans=min(check(s),ans);
59         if(ans==MAX)
60         ans=-1;
61         printf("Case %d: %d
",l,ans);
62     }
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3139249.html