题意:黑白的板,每次选择一个十字形翻转(十字板内黑白互换,若是边界则不管),求最小将原图变为全白的策略。
题解:枚举第一行翻转情况,2^c,然后验证,由于第一行确定了,后面就可以跟着确定了。
View Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 int map[20][20]; 6 int hit[20][20],ahit[20][20]; 7 int ans,r,c; 8 const int inf=1<<30; 9 void on(int x,int y) 10 { 11 hit[x][y]^=1; 12 map[x][y]^=1; 13 map[x-1][y]^=1; 14 map[x+1][y]^=1; 15 map[x][y+1]^=1; 16 map[x][y-1]^=1; 17 } 18 void solve(int k,int cnt) 19 { 20 if(cnt>=ans) 21 return; 22 int i; 23 if(k==r) 24 { 25 for(i=1;i<=c;i++) 26 if(map[r][i]!=0) 27 break; 28 if(i<=c) 29 return; 30 ans=cnt; 31 memcpy(ahit,hit,sizeof(hit)); 32 return; 33 } 34 for(int i=1;i<=c;i++) 35 if(map[k][i]) 36 on(k+1,i),cnt++; 37 solve(k+1,cnt); 38 for(int i=1;i<=c;i++) 39 if(hit[k+1][i]) 40 on(k+1,i); 41 } 42 void dfs(int k,int cnt) 43 { 44 if(cnt>=ans) 45 return; 46 else if(k==c+1) 47 { 48 solve(1,cnt); 49 return; 50 } 51 else 52 { 53 dfs(k+1,cnt); 54 on(1,k); 55 dfs(k+1,cnt+1); 56 on(1,k); 57 } 58 } 59 int main() 60 { 61 while(scanf("%d%d",&r,&c)!=EOF) 62 { 63 ans=inf; 64 for(int i=1;i<=r;i++) 65 { 66 for(int j=1;j<=c;j++) 67 { 68 scanf("%d",&map[i][j]); 69 hit[i][j]=0; 70 } 71 } 72 dfs(1,0); 73 if(ans==inf) 74 printf("IMPOSSIBLE\n"); 75 else 76 { 77 for(int i=1;i<=r;i++) 78 { 79 for(int j=1;j<=c;j++) 80 { 81 if(j!=1) 82 printf(" "); 83 printf("%d",ahit[i][j]); 84 } 85 printf("\n"); 86 } 87 } 88 } 89 return 0; 90 }