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 ;
}

猜你喜欢

转载自blog.csdn.net/just_gong/article/details/107911870
今日推荐