//
// main.cpp
// ACM
//
// Created by 9zai on 3/22/15.
// Copyright (c) 2015 9zai. All rights reserved.
//
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int INF = 1000000;
int num[20][20];
int temp[20][20];
int N;
int check(int s){
memset(temp, 0, sizeof(temp));
for(int c=0;c<N;c++){
if(s & (1<<c)) temp[0][c] = 1;
else if(num[0][c]==1) return INF;//默认为0,所以若num为1则不可能变0
}
for(int r=1;r<N;r++){
for(int c=0;c<N;c++){
int sum =0;//决定的是temp[r][c]的值,但是sum中心却是temp[r-1][c]
if(r>1) sum+=temp[r-2][c];
if(c>0) sum+=temp[r-1][c-1];
if(c<N-1) sum+=temp[r-1][c+1];
temp[r][c] = sum%2;
if(temp[r][c]==0 && num[r][c]==1) return INF;
}
}
int count=0;
for(int r=0;r<N;r++){
for(int c=0;c<N;c++){
if(temp[r][c]!=num[r][c]) count++;
}
}
return count;
}
int main(int argc, const char * argv[])
{
// insert code here...
// cout<<(1<<4)<<endl;..2的n次方
int T;
cin>>T;
for(int kase=1;kase<=T;kase++){
cin>>N;
int ans =INF;
memset(num, 0, sizeof(num));
for(int r=0;r<N;r++){
for(int c=0;c<N;c++){
cin>>num[r][c];//init
}
}
for(int i=0;i < (1<<N);i++){
ans = min(ans,check(i));
}
if(ans == INF ) ans =-1;//
cout<<"Case "<<kase<<": "<<ans<<endl;
}
return 0;
}
解题经历:
根据《入门经典训练指南》进行尝试
解题思路:对于n*n的矩阵,首先对第一行进行枚举(check(i)),后根据第一行进行第二第三行等的推断,最后得到解。
主要收获:
1.对于移位符的认识..1<<c指2的c次方
待处理问题:
1.在check里面 if( s && (1<<c))的作用究竟是什么?为什么下面会有一个else if?不是应该除第一行外都是true吗?
2.main里面对check的调用是在一个for里面的,且循环2^n次,为什么要把次数作为参数传进去?
!!!待处理问题解决:!!
if里面的是 & 而不是&&....&是按位比较,即循环次数s和2^c进行按位比较!!!!这里的就是它对第一行的枚举方法!!!