题目链接: POJ1753
这道题本萌新看了好久大佬学长的代码才看懂...
大致思路:采用位运算和枚举,也就是利用位运算枚举出第一行所有的翻转情况,然后第二三行依据前一行进行翻转,最后通关检查第四行来判断是否达到全白或全黑
我觉得难点在于如何利用位运算来枚举出第一行的所有的情况,建议把代码中st的翻转情况手动列出来,便于理解,真的很巧妙。以及为什么通过翻转(x,y)来间接地翻转(x-1,y)之后,最后只需检查第四行就能判断是否达到要求。
代码如下
1 #include<cstdio> 2 #include<cstring> 3 #define INF 0x3f3f3f3f 4 #define maxn 6 5 using namespace std; 6 7 char piece[maxn][maxn]; 8 int piece_int[maxn][maxn]; 9 int piece_int_copy[maxn][maxn]; 10 11 int min(int a,int b,int c){ 12 a=(a<=b)?a:b; 13 a=(a<=c)?a:c; 14 return a; 15 } 16 17 void flip(int x,int y){//对x,y格子进行反转操作 18 piece_int_copy[x][y]=!piece_int_copy[x][y]; 19 if(x-1>0) piece_int_copy[x-1][y]=!piece_int_copy[x-1][y]; 20 if(y-1>0) piece_int_copy[x][y-1]=!piece_int_copy[x][y-1]; 21 if(x+1<5) piece_int_copy[x+1][y]=!piece_int_copy[x+1][y]; 22 if(y+1<5) piece_int_copy[x][y+1]=!piece_int_copy[x][y+1]; 23 } 24 25 int run(int st,bool isBlack){//st用来进行位运算,isBlack用来判断全白或全黑 26 int cnt=0; 27 memcpy(piece_int_copy,piece_int,sizeof(piece_int)); 28 29 for(int i=0;i<4;i++){//(敲黑板划重点)对第一行反转的情况进行排列组合 30 if((st>>i)&1){ 31 flip(1,i+1); 32 cnt++; 33 } 34 } 35 36 for(int i=2;i<=4;i++){ 37 for(int j=1;j<=4;j++){ 38 if(piece_int_copy[i-1][j]!=isBlack){ 39 flip(i,j); 40 cnt++; 41 } 42 } 43 } 44 45 for(int i=1;i<=4;i++){ 46 if(piece_int_copy[4][i]!=isBlack){ 47 return INF; 48 } 49 } 50 51 return cnt; 52 } 53 54 int main(){ 55 for(int i=0;i<4;i++) 56 scanf("%s",piece[i]); 57 58 for(int i=0;i<4;i++) 59 for(int j=0;j<4;j++) 60 piece_int[i+1][j+1]=piece[i][j]=='b'?1:0; 61 62 int inf=INF; 63 for(int st=0;st<(1<<4);st++){//第一行的翻转情况总共有16种 64 inf=min(inf,run(st,true),run(st,false)); 65 } 66 67 if(inf==INF) 68 printf("Impossible\n"); 69 else 70 printf("%d\n",inf); 71 72 return 0; 73 }