UVA 11464打卡

算法竞赛入门经典训练指南打卡

题目链接:UVA 11464

思路

如果我们要写出一个上述的偶数矩阵,肯定是先确定第一排,然后再根据第一排确定第二排,通过第一排和第二排确定第三排。也就是说我们必须要先确定第一排的数,再推导下面的数。
而每个数都可以是0或者1,所以第一排我们可以使用2进制来确定第一排的数。这样可以使第一排的每种可能都出现。然后我们再通过第一排确定第二排,一直到写出整个偶数矩阵为止。此时判断该矩阵与我们输入的矩阵有多少个地方是变化了的即可
具体的细节可以看代码注释

代码如下:

#include <iostream>
#include <cstring>
#define ton(i , n) for(int i = 0 ; i < n ; ++ i)

using namespace std ;

int a[15][15] , b[15][15] ;
int n ;

int change(int first){
    memset(b , 0 , sizeof(b)) ;         //将b数组置零
    ton(i , n){
        if(first & (1 << i))        //给第一排赋值 当前位置为1 ,则是可行的。因为此时无论输入的数组此时是0还是1,都可以是1
            b[0][i] = 1 ;
        else{
            if(a[0][i] == 1)
                return 300 ;        //当前位置为0,则输入的数组该位置必须为0,否则该方案行不通
        }
    }
    for(int i = 1 ; i < n ; ++ i)
        ton(j , n){
            int sum = 0 ;
            if(i > 1)
                sum += b[i - 2][j] ;    //i > i 的时候是第三批到最后一排,此时需要计算该位置的上上层对应的数
            if(j > 0)
                sum += b[i - 1][j - 1] ;       //j > 0 此时左边不是边界,所以需要加上上一层左边的数字
            if(j < n - 1)
                sum += b[i - 1][j + 1] ;        //j < n - 1的时候右边不是边界,需要加上上一层右边的数字
            b[i][j] = sum % 2 ;         //给当前位置赋值
            if(a[i][j] == 1 && b[i][j] == 0)    //如果当前位置为0,输入数组对应位置为1,则该方案不可行
                return 300 ;
        }
    int ans = 0 ;
    ton(i , n)
        ton(j , n)
            if(a[i][j] != b[i][j])
                ans ++ ;        //计算a数组和b数组中不同的数的个数,即我们改变的数字
    return ans ;
}

int main(){
    int t , k = 1 ;
    cin >> t ;
    while (t --){
        cin >> n ;
        ton(i , n)
            ton(j , n)
                cin >> a[i][j] ;        //输入矩阵到a
        int ans = 300 ;			//最大的也是15 * 15的矩阵,不可能改变300次
        ton(i , (1 << n))	
            ans = min(ans , change(i)) ;    //枚举第一层
        if(ans == 300)
            ans = -1 ;      //如果ans没有变化则说明不存在可以变为偶数矩阵的情况
        cout << "Case " << k ++ << ": " << ans << endl ;
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值