POJ 3279 Fliptile

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<queue>
  5 #include<map>
  6 #include<vector>
  7 #include<set>
  8 #include<string>
  9 #include<cmath>
 10 #include<cstring>
 11 using namespace std;
 12 const int MAX_N=20;
 13 const int MAX_M=20; 
 14 const int dy[5]={-1,0,0,0,1};
 15 const int dx[5]={0,-1,0,1,0};
 16 int M,N;
 17 int title[MAX_M][MAX_N];
 18 int opt[MAX_M][MAX_N];//最优解 
 19 int flip[MAX_M][MAX_N];//中间结果 
 20 
 21 //查询(x,y)的颜色 
 22 int get(int x,int y)
 23 {
 24     int c=title[x][y];//先直接查询c颜色 
 25     for(int d=0;d<5;d++)//再遍历上下左右反转后会影响c的颜色的格子 
 26     {
 27         int x2=x+dx[d],y2=y+dy[d];
 28         if(0<=x2&&x2<M&&0<=y2&&y2<N)
 29         {
 30             c+=flip[x2][y2];//加起来        
 31         }    
 32     }    
 33     return c%2;//1是黑色 0是白色 
 34 } 
 35 //第一行确定后最小操作次数
 36 //不存在返回-1
 37 int calc()
 38 {
 39     //第二行开始的反转方法
 40     for(int i=1;i<M;i++)
 41     {
 42         for(int j=0;j<N;j++)
 43         {
 44             if(get(i-1,j)!=0)
 45             {
 46                 flip[i][j]=1;//    (i-1,j)黑色就转这个格子 
 47             } 
 48         }        
 49     }
 50     //判断最后一行是否全白
 51     for(int j=0;j<N;j++)    
 52     {
 53         if(get(M-1,j)!=0)
 54             return -1;
 55     }
 56     //统计反转次数
 57     int res=0;
 58     for(int i=0;i<N;i++)
 59     {
 60         for(int j=0;j<N;j++)
 61         {
 62             res+=flip[i][j];
 63         }
 64     } 
 65     return res;
 66 } 
 67 void solve()
 68 {
 69     int res=-1;
 70     //按字典序查找第一行所有可能性 
 71     for(int i=0;i<1<<N;i++)
 72     {
 73         memset(flip,0,sizeof(flip));
 74         for(int j=0;j<N;j++)
 75         {
 76             flip[0][N-j-1]=i>>j&1;
 77         }
 78         int num=calc();
 79         if(num>=0&&(res<0||res>num))
 80         {
 81             res=num;
 82             memcpy(opt,flip,sizeof(flip));//储存最优解 
 83         } 
 84     }
 85     
 86     if(res<0) //无解
 87     {
 88         printf("IMPOSSIBLE\n");    
 89     } 
 90     else
 91     {
 92         for(int i=0;i<M;i++)
 93         {
 94             for(int j=0;j<N;j++)
 95             {
 96                 printf("%d%c",opt[i][j],j+1==N?'\n':' ');
 97             }
 98         }
 99     }
100 }
101 int main()
102 {
103     scanf("%d%d",&M,&N);
104     for(int i=0;i<M;i++)
105     {
106         for(int j=0;j<N;j++)
107         {
108             scanf("%d",&title[i][j]);
109         }
110     }
111     solve();
112     return 0;
113 }

 

posted @ 2020-01-31 16:25  付玬熙  阅读(116)  评论(0编辑  收藏  举报