poj1753

来源:互联网 发布:淘宝假面骑士铠武腰带 编辑:程序博客网 时间:2024/05/15 23:50

/*题意:
有4*4的正方形,每个格子要么是黑色,要么是白色,
当把一个格子的颜色改变(黑->白或者白->黑)时,
其周围上下左右(如果存在的话)的格子的颜色也被反转,
问至少反转几个格子可以使4*4的正方形变为纯白或者纯黑?
算法:枚举:
对于每个格子,它要么反转0次,
要么反转1次(当然,它的邻格子也跟着反转),
因为它反转偶数次和反转0次的效果是一样的,
同理反转奇数次的效果和反转1次的效果是一样的。
总共2^16种可能,用二进制枚举,位运算会快一点*/

ps:二进制枚举:

位运算:

while (jump<65536)   //2^16
    {
         jump++;
         jump2=jump;
         for (k=0;k<16;k++) //注意从0开始
         {
            flip[k/4][k%4]=jump2&1; //取末位
            jump2=jump2>>1;//右移一位
         }    

   }     

数组:

int a[17];

while (a[0]==0)     2^16        

{

         a[16]++;    //用数组模拟二进制
         for (i=16;i>=0;i--)
          if (a[i]==2)      //进位
          {
              a[i-1]+=a[i]/2;
              a[i]%=2;
          }
         for (k=0;k<16;k++)
          flip[k/4][k%4]=a[k+1];//k从0开始,a是从1开始

}


#include <iostream>

#include <cstdio>


using namespace std;


bool pieces[4][4],flip[4][4],record[4][4];
//int a[17];
const int maxn=70000;


bool judge()
{
     bool c;
     c=record[0][0];
     for (int i=0;i<4;i++)
      for (int j=0;j<4;j++)
        if (record[i][j]!=c) return false;
     return true;
}


bool fan(bool a)
{
    if (a) return 0;else return 1;
}


void do_flip(int i,int j)
{
    record[i][j]=fan(record[i][j]);
    if (i+1<=3) record[i+1][j]=fan(record[i+1][j]);
    if (j+1<=3) record[i][j+1]=fan(record[i][j+1]);
    if (j-1>=0) record[i][j-1]=fan(record[i][j-1]);
    if (i-1>=0) record[i-1][j]=fan(record[i-1][j]);
}


int main()
{
    char ch;
    int i,j,k,ans=maxn;
    freopen("in.txt","r",stdin);
    for (i=0;i<4;i++)
     for (j=0;j<4;j++)
     {
         cin>>ch;
         if (ch=='b') pieces[i][j]=1;else pieces[i][j]=0;
     }
    for (i=0;i<4;i++)
          for (j=0;j<4;j++) record[i][j]=pieces[i][j];
    if (judge())
    {
          cout<<'0';return 0;
    }
    int jump=0,jump2;
    while (jump<65536)//(a[0]==0) 2^16
    {
         jump++;
         jump2=jump;
         for (k=0;k<16;k++) //注意从0开始
         {
            flip[k/4][k%4]=jump2&1; //取末位
            jump2=jump2>>1;//右移一位
         }         //枚举所有情况,用位运算
         /*a[16]++;    //用数组模拟二进制
         for (i=16;i>=0;i--)
          if (a[i]==2)
          {
              a[i-1]+=a[i]/2;
              a[i]%=2;
          }
         for (k=0;k<16;k++)
          flip[k/4][k%4]=a[k+1];*/ //k从0开始,a是从1开始
         for (i=0;i<4;i++)
          for (j=0;j<4;j++)
           if (flip[i][j]) do_flip(i,j);
         if (judge())
         {
              int sum=0;
              for (i=0;i<4;i++)
               for (j=0;j<4;j++)
                if (flip[i][j]) sum++;
              if (sum<ans)ans=sum;
         }
         for (i=0;i<4;i++)
          for (j=0;j<4;j++) record[i][j]=pieces[i][j];
    }
    if (ans<maxn) cout<<ans;
    else cout<<"Impossible";
    return 0;
}

0 0