POJ 1753 Flip Game (枚举 + 位运算)

题意:有一个4*4的棋盘,棋盘上有黑白格(两面分别为黑白色)。每一次你可以翻其中的一个格子,每翻一个格子,这个格子上下左右的格子(如果有)也会被翻,让你写一个程序,看最后将棋盘全部翻为白色格子或者是黑色格子用的最少的步数是多少?如果无法把所有格子都翻为白色或者是黑色,那么输出“Impossible”。



思路:

因为是4x4的棋盘,而且每个棋子只有黑或白2种状态(可以用01表示),所以整个棋盘的状态可以用一个整数value(只需低16位)来表示,(value==0或者value==0xffff表示只有清一色黑或白)

如果要改变某一位的状态,只要用1来跟那一位进行异或运算。

然后我发现:第一行的四个格子要翻转的状态(1表示翻转,0表示不翻转)分别是:

1100   1110    0111   0011

1000   0100   0010   0001

0000   0000   0000   0000

0000   0000   0000   0000

分别用0xc800, 0xe400, 0x7200, 0x3100来异或。后面的同理找出规律。

第二行用0x8c80, 0x4e40, 0x2720, 0x1310

第三行用0x08c8, 0x04e4, 0x0272, 0x0131

第四行用0x008c, 0x004e, 0x0027, 0x0013


#include<iostream>
#include<climits>
using namespace std;
const int M = INT_MAX;
typedef long long LL;
int flip[16]={0xc800, 0xe400, 0x7200, 0x3100, 0x8c80, 0x4e40, 0x2720, 0x1310, 0x08c8, 0x04e4, 0x0272, 0x0131, 0x008c, 0x004e, 0x0027, 0x0013};

int main(){
    /*初始化check,用于检查一个二进制位上是否为1*/
    int check[16];
    for(int i=0;i<16;i++)
        check[i]=(1<<(15-i));

    int value=0, Min_step=M;
    for(int i = 0; i < 16; i++){
        char c;
        cin >> c;                   //cin自动过滤回车
        if(c == 'b')
            value = (value<<1) + 1;
        else value<<=1;
    }

    for(int i=0; i<(1<<16); i++){                   //i的二进制位中,1表示要翻,0表示不翻
        int t_value=value, step=0;
        for(int j=0; j<16; j++){                  //检查i从左到右每个二进制位是不是1
            if(i&check[j]){                    //如果是1就要翻转value二进制中的该位
                t_value^=flip[j];
                step++;
            }
        }
        if(t_value==0||t_value==0xffff){
            if(step < Min_step) Min_step=step;
        }
    }
    if(Min_step!=M) cout<<Min_step<<endl;
    else cout<<"Impossible"<<endl;
    return 0;
}

同类型题: POJ 2965
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值