poj3279Fliptile

题目链接:http://poj.org/problem?id=3279
二进制枚举第一行需要翻转的位置,推出剩余行的翻转情况,若最后一行不需翻转则更新答案,否则此方案失败继续枚举下一种。


1
#include<cstdio> 2 #include<cstring> 3 const int maxn=18; 4 int g[maxn][maxn],op[maxn][maxn],temp[maxn][maxn]; 5 int n,m; 6 int tp; 7 int dis[5][2]={0,0,0,1,0,-1,1,0,-1,0}; 8 9 int need(int r,int l) //判断(r+1,l)是否需要翻转 10 { 11 int ct=g[r][l]; 12 for(int i=0;i<5;i++) 13 { 14 int dx=r+dis[i][0]; 15 int dy=l+dis[i][1]; 16 if(dx>=0&&dx<n&&dy>=0&&dy<m&&temp[dx][dy]) 17 ct++; 18 } 19 return ct%2; 20 21 } 22 void flip() 23 { 24 for(int i=1;i<n;i++) 25 for(int j=0;j<m;j++) 26 if(need(i-1,j)) temp[i][j]=1; 27 28 for(int i=0;i<m;i++) //如果最后一行还需翻转,则此方案失败 29 if(need(n-1,i)) 30 { 31 tp=0; 32 return; 33 } 34 for(int i=0;i<n;i++) 35 for(int j=0;j<m;j++) 36 if(temp[i][j]) tp++; 37 } 38 int main() 39 { 40 while(scanf("%d%d",&n,&m)!=EOF) 41 { 42 int ans=1e9; 43 for(int i=0;i<n;i++) 44 for(int j=0;j<m;j++) 45 scanf("%d",&g[i][j]); 46 for(int i=0;i<(1<<m);i++) //二进制枚举第0行的状态 47 { 48 memset(temp,0,sizeof(temp)); 49 tp=0; 50 for(int j=0;j<m;j++) 51 temp[0][j]=(i>>j)&1; 52 flip(); 53 if(ans>tp&&tp>0) //更新答案 54 { 55 ans=tp; 56 memcpy(op,temp,sizeof(temp)); 57 } 58 } 59 if(ans==1e9) puts("IMPOSSIBLE"); 60 else 61 for(int i=0;i<n;i++) 62 for(int j=0;j<m;j++) 63 printf("%d%c",op[i][j],j==m-1?' ':' '); 64 } 65 66 }
原文地址:https://www.cnblogs.com/yijiull/p/6594508.html