UVA11464 Even Parity 搜索+递推
问题描述
题解
第一直觉爆搜。
发现 \(N \le 15\) ,然后后面每行都可以通过第一行递推出来。
爆搜第一行,递推后面+check
\(\mathrm{Code}\)
#include<bits/stdc++.h>
using namespace std;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') ch=getchar(),fh=-1;
else fh=1;
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=fh;
}
const int maxn=17;
const int INF=0x3f3f3f3f;
int T,cas;
int n;
int a[maxn][maxn],b[maxn][maxn];
int ans;
int calc(){
int res=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]==1&&b[i][j]==0) ++res;
}
}
return res;
}
bool check(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int k=a[i][j-1]+a[i][j+1]+a[i-1][j]+a[i+1][j];
if(k&1) return false;
}
}
return true;
}
void rebuild(){
for(int i=2;i<=n;i++){
for(int j=1;j<=n;j++) a[i][j]=b[i][j];
}
}
void dp(){
for(int i=2;i<=n;i++){
for(int j=1;j<=n;j++){
int k=a[i-1][j-1]+a[i-1][j+1]+a[i-2][j];
if(k&1) a[i][j]=1;
}
}
if(!check()){
rebuild();return ;
}
ans=min(ans,calc());
rebuild();
}
void dfs(int step){
if(step==n+1){
dp();return;
}
if(a[1][step]){
dfs(step+1);return;
}
dfs(step+1);
a[1][step]=1;
dfs(step+1);
a[1][step]=0;
}
void Init(){
read(n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
read(a[i][j]);
b[i][j]=a[i][j];
}
}
}
void solve(){
dfs(1);
if(ans==INF) ans=-1;
printf("Case %d: %d\n",cas,ans);
}
void reset(){
ans=INF;
memset(a,0,sizeof(a));//错误笔记:多测不清空,*****
memset(b,0,sizeof(b));
}
int main(){
// freopen("UVA11464.in","r",stdin);freopen("UVA11464.out","w",stdout);
read(T);
while(T--){
++cas;
reset();
Init();solve();
}
return 0;
}