状态压缩

定义

状态压缩,实际上是将一个30左右长度的bool数组用一个int来表示。为什么呢?众所周知,bool类型只有0,1两种两种类型。而计算机又是用二进制来存储数字,加之强大的位运算功能,我们便可以更改整数在二进制下表示的每一位的数字,来表示不同的状态。由于其与位运算密切相关,所以我们先来讨论一下位运算的事情。

位运算

不做演示,可以自行演示验证

S是原集合

S&(1<<(k-1))   取出第k位
 ^             将第k位取反
 |             将第k位强制变1
S^(1<<k-1)       取补集 
S&(-S)         取出右起第一个1  ,减掉这个结果数就更新状态 lowbit
S|A==S         A是S的子集
for(x=s;x;s&(x-1)  枚举子集

题目中的ShowTime

开关游戏

 

 何以状态压缩?唯开关亮灭与否也!

开关矩阵是4*4,所以状态数只有16个,完全可以状态压缩

然后通过宽搜枚举每个按键,注意通过位运算判断边界情况。

一定要记得先判断是否初始状态已经全部亮起或全部熄灭。

#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN=65536;
int start;
int Pow[16]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,8192,16384};
bool Appear[MAXN];
int step[MAXN];
queue<int> Q;
int ans;
int click(int h,int i){
    h^=(1<<i);
    if((i)%4!=0){
        h^=(1<<(i-1));
    }
    if((i+1)%4!=0){
        h^=(1<<(i+1));
    }
    if(i>=4){
        h^=(1<<(i-4));
    }
    if(i<=11){
        h^=(1<<(i+4));
    }
    return h;
}
int bfs(){
    Q.push(start);
    step[start]=0;
    Appear[start]=true;
    while(!Q.empty()){
        int h=Q.front();
        Q.pop();
        for(int i=0;i<=15;i++){
            int st=click(h,i);
            if(!Appear[st]){
                if(st==0||st==65535){
                    return step[h]+1;
                    
                }
                    Appear[st]=true;
                    Q.push(st);
                    step[st]=step[h]+1;
            }
        }
    }
    cout<<"Impossible";
    return 0;
}
int main(){
//   int p=16; 
//    while(p>0){ 
//        char ch=getchar(); 
//        if(ch=='w'||ch=='b'){ 
//            if(ch=='w')start+=(1<<(p-1)); 
//            p--; 
//        } 
//    } 
    for(int i=15;i>=0;i--){
        char ch=getchar();
        if(ch=='w'||ch=='b'){
            if(ch=='w')start+=(1<<(i));
        }
        else{
            i++;
        }
    }
    if(start==65535||start==0){
        cout<<0;
        return 0;
    }
    ans=bfs();
    if(!ans){
        //cout<<"Impossible";
    }
    else{
        cout<<ans;
    }
        
}

 

转载于:https://www.cnblogs.com/Uninstalllingyi/p/11432672.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值