POJ1753(位操作和枚举)

题目:http://poj.org/problem?id=1753

题意:一块4*4的棋盘,黑白块不规律分布,翻动一个色块,其上下左右,都会被翻动,知道全黑全白为止。输出最小次数,达不到则输出“Impossible"

理解:每块棋盘只有两种表示 黑白  只有16个色块 可以用16位的二进制表示

       1 1 1 1              1   2   3   4

       1 1 1 1      转化为         5   6   7   8

       1 1 1 1                      9  10 11 12

       1 1 1 1              13 14 15 16

位运算:异或(^)可以实现翻转 1^1=0  0^1=1

 a.   1 1 1 1

       1 1 1 1

       1 1 1 1           表示为1100 1000 0000 0000    51200

       1 1 1 1

 b.

    1 1 1 1

    1 1 1 1

    1 1 1 1           表示为1110 0100 0000 0000    58368

    1 1 1 1

etc......

#include<iostream>
const int MAX=999999;
using namespace std;
int arr[16]= {19,39,78,140,305,626,1252,2248,4880,8992,20032,35968,12544,29184,58368,51200};//只有一位是1,其余是零
int num[16]= {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};//对照操作的数
int main()
{
    int i,j,value=0;
    int cmin=MAX;
    char c;
    for( i=0; i<16; i++)
    {
        cin>>c;
        if(c=='b')
            value+=num[i];//使黑色的位置 对应 为1 
        else  continue;
    }
    for( i=0; i<65536; i++)//2^16 个数  i代表了每种翻牌方案
    {
        int cnt=0;
        int cvalue=value;
        for(j=0; j<16; j++)//j 分别实现每个色块的翻牌操作
            if(i&num[j])// 比如 0110 与 0010  则决定第二个色块的翻牌 0110 与0100  则决定第三个色块的翻牌
            {
                cnt++;
                cvalue^=arr[j];//异或 实行翻牌
            }
         if(cvalue==0||cvalue==65535)
        {
            if(cnt<cmin)cmin=cnt;
        }

    }
    if(cmin==MAX) cout<<"Impossible";
    else cout<<cmin<<endl;
    return 0;
}

  

原文地址:https://www.cnblogs.com/sxy-798013203/p/5741324.html