kb-01-d<poj3279>--深搜变种,二进制优化;

poj--3279

题意:

    给n*m的矩阵,0 1组成,每次翻转一个格子可以将上下左右的五个节点翻转,求,把所有的格子翻转成0;输出每个个字的翻转次数;最少字数;

做法:

从上到下,第一行翻转的情况确定的话就全确定了;因此只要枚举第一行的翻转情况就可以了;

第一行翻转0次或1次;所以可以用二进制化,不用dfs了;具体看代码实现;

对于每一种第一行看需要翻转的次数是否是最小的;

代码如此:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #define inf 0x3f3f3f3f
  6 using namespace std;
  7 int n,m,ans;
  8 int a[20][20],vis[20][20]={0},t[20][20]={0},p[5][2]={0,0,0,1,0,-1,1,0,-1,0},an[20][20]={0};
  9 bool s[20];      //vis数组用来记录主动翻转的情况;t数组用来记录一共翻转的次数;an数组用来记录最终结果;
 10 int solve()         //根据第一行的情况确定剩余所有行的情况;
 11 {
 12     for(int i=0;i<m;i++)
 13     {
 14         if(vis[0][i]==1)
 15         {
 16             t[0][i]++;
 17             if(n>1)
 18             t[1][i]++;
 19             if(i<m-1)
 20             t[0][i+1]++;
 21             if(i>0)
 22             t[0][i-1]++;
 23         }
 24     }
 25     for(int i=1;i<n;i++)
 26     {
 27         for(int j=0;j<m;j++)
 28         {
 29             if(t[i-1][j]%2!=a[i-1][j])
 30             {
 31                 vis[i][j]=1;
 32                 for(int z=0;z<5;z++)
 33                 {
 34                     int x=i+p[z][0],y=j+p[z][1];
 35                     t[x][y]++;
 36                 }
 37             }
 38         }
 39     }
 40     for(int i=0;i<n;i++)
 41     {
 42         for(int j=0;j<m;j++)
 43         {
 44             if(t[i][j]%2!=a[i][j])
 45                 return 0;
 46         }
 47     }
 48     return 1;
 49 }
 50 int main()
 51 {
 52     while(cin>>n>>m)
 53     {
 54         memset(a,0,sizeof(a));
 55         memset(vis,0,sizeof(vis));
 56         memset(t,0,sizeof(t));
 57         ans=inf;
 58         for(int i=0;i<n;i++)
 59         {
 60             for(int j=0;j<m;j++)
 61             {
 62                 scanf("%d",&a[i][j]);
 63             }
 64         }
 65        for(int i=0;i<pow(2.0,m);i++)
 66        {
 67            memset(vis,0,sizeof(vis));
 68            for(int j=m-1;j>=0;j--)
 69            {
 70                s[j]=i&(1<<j);
 71                vis[0][j]=s[j];
 72            }
 73            memset(t,0,sizeof(t));
 74            int temp=solve(),cou=0;
 75            if(temp==1)
 76            {
 77                for(int i=0;i<n;i++)
 78                {
 79                    for(int j=m-1;j>=0;j--)
 80                    {
 81                        if(vis[i][j]==1)
 82                             cou++;
 83                    }
 84                }
 85                if(cou<ans)
 86                {
 87                    ans=cou;
 88                    for(int i=0;i<n;i++)
 89                    {
 90                        for(int j=m-1;j>=0;j--)
 91                            an[i][j]=vis[i][j];
 92                    }
 93 
 94                }
 95            }
 96        }
 97        if(ans!=inf)
 98            for(int i=0;i<n;i++)
 99            {
100                for(int j=0;j<m;j++)
101                {
102                    if(j!=0)
103                        printf(" ");
104                    printf("%d",an[i][j]);
105                }
106                printf("\n");
107            }
108        else
109            printf("IMPOSSIBLE\n");
110     }
111 
112     return 0;
113 }
View Code

 

posted on 2015-04-14 17:17  bai_yan  阅读(192)  评论(0编辑  收藏  举报

导航