UVA 11464 偶数矩阵(递推 | 进制)

题目链接:https://vjudge.net/problem/UVA-11464

一道比较好的题目。

思路如下:

如果我们枚举每一个数字“变”还是“不变”,那么需要枚举$2^{255}$种情况,很显然不行。

那么我们就来优化一下:我们只枚举第一行的数,然后根据计算得出第二、三....行的数。

这样复杂度就优化到了$O(2^n imes n^2)$。

然后用$A[][]$和$B[][]$分别表示变化前后的矩阵。

那么现在的问题就简化成了如何枚举第一行和如何递推。

枚举第一行:运用了状压的思想,把一行数看成一个二进制数,然后$&(1<<c)$,看是否为1,由此我们就构造了一个如下图所示的矩阵。

递推方法:

求出$B[r-1][c]$的上、左、右数之和,如果为偶数,则$B[r][c]=0$,反之$B[r][c]=1$。

在递推中如果发现由$1$转变到$0$的情况,那么是不可能的。

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 const int maxn=15;
 8 const int INF=0x7f7f7f;
 9 int n,A[maxn][maxn],B[maxn][maxn];
10 
11 int check(int s){
12     memset(B,0,sizeof(B));
13     for(int c=0;c<n;c++){
14         if(s&(1<<c)) B[0][c]=1;
15         else if(A[0][c]==1) return INF;
16     }
17     for(int r=1;r<n;r++){
18         for(int c=0;c<n;c++){
19             int sum=0;
20             if(r>1) sum+=B[r-2][c];
21             if(c>0) sum+=B[r-1][c-1];
22             if(c<n-1) sum+=B[r-1][c+1];
23             B[r][c]=sum%2;
24             if(A[r][c]==1&&B[r][c]==0) return INF;
25         }
26     }
27     int cnt=0;
28     for(int r=0;r<n;r++)
29         for(int c=0;c<n;c++) if(A[r][c]!=B[r][c]) cnt++;
30     return cnt;
31 }
32 
33 int main(){
34     int T;
35     scanf("%d",&T);
36     for(int k=1;k<=T;k++){
37         scanf("%d",&n);
38         for(int r=0;r<n;r++)
39             for(int c=0;c<n;c++) scanf("%d",&A[r][c]);
40         int ans=INF;
41         for(int s=0;s<(1<<n);s++)
42             ans=min(ans,check(s));
43         if(ans==INF) ans=-1;
44         printf("Case %d: %d
",k,ans);
45     }
46     return 0;
47 }
AC代码
原文地址:https://www.cnblogs.com/New-ljx/p/12284248.html