且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

uva 11464 - Even Parity

更新时间:2022-08-19 22:26:47

点击打开链接uva11464

思路:模拟
分析:
1 由题目可知矩阵的最大的行数为15,那么我们最容易想到就是去枚举每一个位置的数,那么矩阵的最多的元素为255,那么255个元素的状态为2^255,很明显这个是不可能实现的。
2 那么我们相到第一行的状态最多为2^15的,那么我们知道如果一个矩阵满足题目要求的话就是每一个元素的周围四个元素之和为偶数,那么我们就可以通过第一行求出第二行,利用第二行求出第三行...
3 那么我们只要去枚举第一行的2进制的每一个值,然后判断即可。

代码:

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

const int INF = 1<<30;
const int MAXN = 20;
int m[MAXN][MAXN];

int solve(int n , int s){
    int tmp[MAXN][MAXN];
    memset(tmp , 0 , sizeof(tmp));
    for(int i = 0 ; i < n ; i++){
       if(s & (1<<i))//说明这一位是1
          tmp[0][i] = 1;
       else if(m[0][i] == 1)//这里得到的是0,但是实际上1不可能存在
          return INF;
    }
    //求出tmp数组
    for(int i = 1 ; i < n ; i++){
       for(int j = 0 ; j < n ; j++){
          int sum = 0;//通过前一行求出下一行
          if(i > 1)//加上
             sum += tmp[i-2][j];
          if(j > 0)//加左
             sum += tmp[i-1][j-1];
          if(j < n-1)
             sum += tmp[i-1][j+1];
          //通过sum求出第tmp[i][j];
          if(sum%2)//如果sum为奇数
             tmp[i][j] = 1;
          if(tmp[i][j] == 0 && m[i][j] == 1)//如果现在为0但是原先为1这种情况是不可能的
             return INF;
       }
    }
    //求出这次的变换的次数
    int cnt = 0;
    for(int i = 0 ; i < n ; i++)
       for(int j = 0 ; j < n ; j++)
          if(m[i][j] != tmp[i][j])
             cnt++;
    return cnt;
}

int main(){ 
    int Case , n , cnt = 1;
    scanf("%d" , &Case);
    while(Case--){
        scanf("%d" , &n);
        for(int i = 0 ; i < n ; i++)
           for(int j = 0 ; j < n ; j++)
              scanf("%d" , &m[i][j]);
        int ans = INF;
        for(int i = 0 ; i < (1<<n) ; i++)//枚举第一行的状态
           ans = min(ans , solve(n , i));//求最小的ans
        printf("Case %d: %d\n" , cnt++ , ans == INF ? -1 : ans);
    }
    return 0;
}