题目地址: http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=4304
直接 DFS 枚举所有可能即可。。
#include<stdio.h>
#include<string.h>
int s[5][5],res,r[5][5],k[5][5];
void output(){ // 这题很早就做出来了。。 查了一小时错。囧
// 错在最后的输出 这里,一直被忽略了,把 r[3][1] 写成了 r[3][i] 。。。
int i;
putchar(' ');
for(i=2;i<=3;i++)
printf(" %d",r[1][i]);
putchar('\n');
printf("%d",r[2][1]);
for(i=2;i<=4;i++)
printf(" %d",r[2][i]);
putchar('\n');
printf("%d",r[3][1]);
for(i=2;i<=4;i++)
printf(" %d",r[3][i]);
putchar('\n');
putchar(' ');
for(i=2;i<=3;i++)
printf(" %d",r[4][i]);
putchar('\n');
}
int x[12]={1,1,2,2,2,2,3,3,3,3,4,4}; // 记录所有点的位置
int y[12]={2,3,1,2,3,4,1,2,3,4,2,3};
int same(){ // 判断所有颜色是否一致
int i,sum=0;
for(i=0;i<12;i++)
if(s[x[i]][y[i]]) sum++;
if(sum==0 || sum==12) return 1;
else return 0;
}
void dfs(int num,int i){
if(res>2) return;
if(num==0){
if(same()){
res++; // 记录翻转成功的次数
if(res==1){ // 记录第一次 完成任务时的 所改变的位置。
for(int i=0;i<12;i++)
r[x[i]][y[i]]=k[x[i]][y[i]];
}
}
return;
}
for(;i>=num;i--){
int t=i-1;
for(int j=1;j<=4;j++) // 这里是翻转颜色
s[j][y[t]]^=1,s[x[t]][j]^=1;
s[x[t]][y[t]]^=1;
k[x[t]][y[t]]=1; // 用于记录每次改变了哪个位置
dfs(num-1,i-1);
k[x[t]][y[t]]=0; // dfs 结束之后需要会重新翻转回来
for(int j=1;j<=4;j++)
s[j][y[t]]^=1,s[x[t]][j]^=1;
s[x[t]][y[t]]^=1;
}
}
int main(){
int t,i,j;
scanf("%d",&t);
memset(k,0,sizeof(k));
while(t--){
for(i=0;i<12;i++)
scanf("%d",&s[x[i]][y[i]]);
// 暴力枚举每一种情况, 因为最多翻转12个位置,时间为 2^12 次方
for(i=0;i<=12;i++){ // 从翻转个数少的开始枚举,0个、1个、2个、3个 , 等等
res=0;
dfs(i,12);
if(res>0) break;
}
printf("%d\n",i);
if(res>1) puts("123.cpp");
else output();
}
return 0;
}