zoukankan      html  css  js  c++  java
  • 洛谷P2622关灯问题-状态压缩广度优先搜索

    具体解法是:对队首的某一状态,枚举每一个开关灯操作,记录到达这一新状态的步数(也就是老状态 + 1),若是最终答案,输出,若不是,压入队列。采用结构体记录每个节点,包含当前状态和步数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef struct{
    	int status,cnt;
    }NODE;
    int vis[100020]={0};
    int arr[200][200]={0};
    int n,m;int num=0,min_step=9999;
    queue<NODE> steps;
    
    void bfs(int level)
    { 
    	if(steps.empty())return;
    	NODE pre_node=steps.front();
    	steps.pop();
    	if(pre_node.status==0)
    	{
    		cout<<pre_node.cnt;
    		min_step=min(min_step,pre_node.cnt);
    		return;
    	}
    	for(int i=1;i<=m;i++)
    	{//枚举所有状态
    		NODE new_node=pre_node;
    		int new_status=new_node.status;
    		for(int j=1;j<=n;j++)
    		{
    			if(arr[i][j]==1)
    			{
    				if(new_status&(1<<(n-j)))//说明是1
    					new_status=new_status^(1<<(n-j));
    			}
    			if(arr[i][j]==-1)
    			{
    				new_status=new_status|(1<<(n-j));
    			}
    		}
    
    		if(!vis[new_status])
    		{
    			new_node.status=new_status;
    			new_node.cnt=level;
    			steps.push(new_node);
    			vis[new_status]=1;
    		}
    	}
    	bfs(steps.front().cnt+1);
    }
    int main()
    {
    	cin>>n>>m;
    	for(int i=0;i<n;i++)
    		{
    			num=(num<<1)+1;
    		}
    	NODE node={num,0};
    	steps.push(node);
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=1;j<=n;j++)
    			cin>>arr[i][j];
    	}
    	vis[num]=1;
    	bfs(1);
    	if(min_step==9999) cout<<-1<<endl;
    	return 0;
    }
    

    较为简便的递推dp代码:

    #include<bits/stdc++.h>
    using namespace std;
    vector<int>dp(1025,-1);int arr[200][200];
    int n,m;
    int main()
    {
    	queue<int>q;
    	cin>>n>>m;
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=1;j<=n;j++)
    			cin>>arr[i][j];
    	}
    	q.push((1<<n)-1);dp[(1<<n)-1]=0;
    	while(!q.empty())
    	{
    		
    		int c_state=q.front();
    		q.pop();
    		for(int i=1;i<=m;i++)
    		{
    			int n_state=c_state;
    			for(int j=1;j<=n;j++)
    			{
    				if(arr[i][j]==1)
    					if(n_state&(1<<(n-j)))
    					n_state=n_state^(1<<(n-j));
    				if(arr[i][j]==-1)
    					n_state=n_state|(1<<(n-j));
    			}
    			//cout<<dp[n_state]<<endl;
    			if(dp[n_state]==-1)
    			{	
    				dp[n_state]=dp[c_state]+1;
    				q.push(n_state);
    			}
    		}
    	}
    	cout<<dp[0]<<endl;
    	return 0;
    }
    
    作者:xmsi
    出处:http://www.cnblogs.com/tldr/
    本文版权归作者和博客园共有,欢迎转载,但转载时请保留此段声明。
  • 相关阅读:
    cnblogs看板娘设置
    Docker Secret加密
    坑(十四)—— mysql版本不同导致mysqldump的错误
    坑(十三)—— 制作系统服务时ExecStart脚本后台启动任务导致启动失败
    使用https代替http
    codeblocks opengl glew freeglut 2020.11.15
    Compare the Triplets
    windows桌面编程--监听全局键盘鼠标事件
    基于mosquitto的嵌入式平台MQTT消息推送服务的搭建与使用示例
    openswan在嵌入式平台的集成手记
  • 原文地址:https://www.cnblogs.com/tldr/p/10890378.html
Copyright © 2011-2022 走看看