Even Parity UVA - 11464

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

const int MAXN = 20;
const int INF = 1000000000;
int n, A[MAXN][MAXN], B[MAXN][MAXN];        //原始数组,枚举数组(终态数组)

int check(int s) {
    memset(B, 0, sizeof(B));
    for(int c = 0; c < n; ++c) {    //枚举第一行
        if(s & (1 << c)) {          //检查每一位的状态,如果是1, 则把枚举数组改成1
            B[0][c] = 1;
        } else if(A[0][c] == 1) {   //枚举数组是0, 但是原始数组是1,由原始数组得不到此状态,1不能变为0
            return INF;
        }
    }
    for(int r = 1; r < n; ++r) {
        for(int c = 0; c < n; ++c) {//遍历数组元素
            int sum = 0;            //元素B[r - 1][c]的上,左,右三个元素之和
            if(r > 1) {
                sum += B[r-2][c];   //存在上元素时
            }
            if(c > 0) {             //存在左元素时
                sum += B[r-1][c-1];
            }
            if(c < n-1) {           //存在右元素时
                sum += B[r-1][c+1];
            }
            B[r][c] = sum % 2;      //计算出当前元素的值
            if(A[r][c] == 1 && B[r][c] == 0) {//所得结果应该是1, 但枚举出的却是0,1不能变成0,不符合要求
                return INF;
            }
        }
    }

    int cnt = 0;
    for(int r = 0; r < n; ++r) {            //符合要求,求出来枚举数组与初始数组的不同元素个数,即0->1的个数
        for(int c = 0; c < n; ++c) {
            if(A[r][c] != B[r][c]) {
                cnt++;
            }
        }
    }
    return cnt;
}


int main() {
    int t, cases = 0;
    scanf("%d", &t);
    //  for(int cases = 0; cases < t; ++cases)
    while(t--) {
        scanf("%d", &n);
        for(int r = 0; r < n; ++r) {
            for(int c = 0; c < n; ++c) {
                scanf("%d", &A[r][c]);
            }
        }

        int ans = INF;
        for(int s = 0; s < (1 << n); ++s) {         //枚举
            ans = min(ans, check(s));               //取最小值
        }
        if(ans == INF) {
            ans = -1;
        }
        printf("Case %d: %d\n", ++cases, ans);
    }
    return 0;
}

思路枚举,枚举第一行的状态,然后根据第一行的状态,计算出以下几行的数值,并与初始数组比较并处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值