• 状态压缩入门


    洛谷P2622 关灯问题II

    关灯问题——状态压缩经典 所谓状态压缩

    就是将问题可能遇到的每一个状态用一个唯一的二进制数表示

    其复杂度一般都是指数级的 这也注定了状压类的题数据规模都不会太大


    此题中我们以1表示开灯状态,0表示关灯状态

    这样我们可以以一个长度为n的二进制数唯一的表示每个状态

    接着就可以依靠既定的开关关系将每个状态连接起来

    通过BFS解决

    以灯全开状态为起点

    二进制为n个1 ,十进制表示为(1<< n)-1

    开始枚举m个开关以得到接下来的m个状态

    for(int i=1;i<=m;i++)
    {
        ss=(1<< n)-1;
        for(int j=1;j<=n;j++)
        {
            if( a[i][j]==1 && (ss&(1<<j-1)) ) ss^=(1<<j-1);
            else if( a[i][j]==-1 && !(ss&(1<<j-1)) ) ss|=(1<<j-1);
        }      
    }
    

      

    ss&(1<< j-1)此运算用以检查当前状态的第j位是否为1

    1<< j-1意思是将1左移j-1位,移动后只有第j位上是1

    若开关操作为1且当前状态第j位是1

    则ss^=(1<< j-1) 表示 1与1异或后得0

    若开关操作为-1且当前状态第j位是0

    则ss|=(1 << j-1) 表示 1或0 后得1 (此处异或操作也对,因为1异或0得1)

    之后便用相同的方法在得到的每个状态上再不断搜索每个状态

    由于是BFS,所以一旦某一步状态表示为0(十进制二进制的0写法都是0)

    则当前步数必定是最短操作数

    若遍历完所有状态都没有0,则输出-1

    记得搜索过的状态要打vis标记避免重复访问

    #define ll long long 
    #define rep1(i,a,b) for(int i=a;i<=b;i++)
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    #include <iostream>
    #include <queue>
    using namespace std;
    const int e = (int)105;
    int m,n;
    int a[e][e];
    int vis[1000010];
    struct node
    {
    	int u;
    	int s;
    };
    int bfs(){
    	queue<node>q;
    	int ss ;
    	vis[(1<<n)-1]=1;
    	q.push((node){(1<<n)-1,0});
    	while(!q.empty()){
    		node aa=q.front();
    		q.pop();
    	//	cout << aa.u << '
    ';
    		if(aa.u==0)
    			return aa.s;
     		rep1(i,1,m){
     			ss=aa.u;
     			rep1(j,1,n){
     			//	cout << aa.u << '
    ';
     				if(a[i][j]==1&&(ss&(1<<j-1)))
     					ss^=(1<<j-1);
     				else if(a[i][j]==-1&&!(ss&(1<<j-1)))
     					ss|=(1<<j-1);
     				
     			}
     			if(!vis[ss])
     			{
     			//	cout << aa.u << "***" << '
    ';
     				q.push((node) {ss,aa.s+1});
     				vis[ss]=1;
     			}
     		}
    
    	}
    	return -1;
    }
    
    int main(int argc, char const *argv[])
    {
    	ios::sync_with_stdio(false);
    	cin >> n >> m;
    	rep1(i,1,m){
    		rep1(j,1,n){
    			cin >> a[i][j];
    		}
    	}
    	cout << bfs() << '
    ';
    	return 0;
    }
    

      

    人十我百 人百我万
  • 相关阅读:
    导出PDF乱码
    C/S模式下的打印方法
    填报表导出excel后不可写的单元格处于锁定状态
    多表批量导出txt及打压缩包下载
    客户端定时自动打印页面的例子
    套打中的自定义纸张设置
    linux客户端打印报表时操作系统的配置
    大数据量报表APPLET打印分页传输方案
    Python中类的定义及使用
    Solr7.7高级应用【MLT相似文档搜索、自动补全、自动纠错】
  • 原文地址:https://www.cnblogs.com/bestcoder-Yurnero/p/10763182.html
Copyright © 2020-2023  润新知