题意简单,目标就是求把棋子按特定规则翻成一个颜色的最小步数。注意到以“中心棋子”为准,中心棋子翻n次皆等价于翻0/1次,最优解不可能使同一中心子翻大于1次,因此最优方案的每一步中心子都是互不相同的,由此题目沦为暴力枚举中心子的水题。。。。。
有很多人写了bfs+bit压缩,个人觉得以这题的数据量写那么华丽辛苦了。。。 暴力递归碾过:
1#include<cstdio>
2#include<cstring>
3bool p[5][5],pt[5][5];
4int dir[5][2]={ {0,0},{0,-1},{0,1},{1,0},{-1,0} };
5int w,b;
6int res,max;
7bool find;
8
9void dfs(int sou,int depth,int path[]){
10 int i,j,x,y,xx,yy,bt,wt;
11 if(find) return ;
12 path[depth]=sou;
13 if( depth >= max ){
14 wt=w; bt=b;
15 for(i=0;i<4;i++) for(j=0;j<4;j++) pt[i][j]=p[i][j];
16 for(i=1;i<=max;i++){
17 x=path[i]/4; y=path[i]%4;
18 for(j=0;j<5;j++){
19 xx=x+dir[j][0]; yy=y+dir[j][1];
20 if( xx+1 && 4-xx && yy+1 && 4-yy ){
21 if(pt[xx][yy]){ --bt; ++wt; }
22 else { ++bt; --wt; }
23 pt[xx][yy]=!pt[xx][yy];
24 }
25 }
26 }
27 if( bt == 16 | wt == 16 ) {
28 find = true; res=max;
29 }
30 return ;
31 }
32 else{
33 for(i=sou+1;i<=15-(max-(depth+1));i++) dfs(i,depth+1,path);
34 }
35}
36
37int main(){
38 int i,j,depth;
39 char k;
40 int path[17];
41
42 for(i=0;i<4;i++,getchar())
43 for(j=0;j<4;j++){
44 scanf("%c",&k); p[i][j]=(k-'w')?1:0;
45 if(k-'w') ++b;
46 else ++w;
47 }
48 res=-1;
49 find=false;
50 for(max=0;max<=16;max++)
51 for(i=0;i<=15-(max-(0+1));i++)
52 if( !find ) dfs(i,1,path);
53 if( -1 == res ) printf("Impossible\n");
54 else printf("%d\n",res);
55
56 return 0;
57}