zoukankan      html  css  js  c++  java
  • 【洛谷P2622】关灯问题II【BFS】【状压】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P2622
    mm个开关和nn盏灯,第ii个开关要么可以开启第jj盏灯,要么可以关上第jj盏灯,要么不对第jj盏灯起作用。求把nn盏灯全部打开的最少步数。


    思路:

    这道题很明显可以用BFSBFS做。因为对于每一种情况,我们也就只有mm种转移方法,而求的是最优解。
    而最多只有10盏灯,所以可以想到用状压。这样每种情况就被压缩成了00~10231023中的一个数。
    那么搜就好了。
    注意细节。


    代码:

    #include <cstdio>
    #include <queue>
    using namespace std;
    
    int n,m,a[101][11];
    bool p[1024];
    
    int change(int x,int y)  //转换
    {
    	for (int i=1;i<=n;i++)
    	{
    		if (a[y][i]==1) x|=(1<<(n-i)); 
    	    //如果这个开关可以打开这盏灯,那么就直接或,因为1 or 1=0 or 1=1
    		if (a[y][i]==-1&&(x&(1<<(n-i)))) x^=(1<<(n-i));
    		//如果这个开关可以关上这盏灯,那么就要判断这一位是不是1,如果是1才异或。
    	}
    	return x;
    }
    
    void bfs()
    {
    	queue<int> dis;  //最小步数
    	queue<int> q;  //状态(已压缩)
    	q.push(0);
    	dis.push(0);
    	while (q.size())
    	{
    		int u=q.front();
    		int d=dis.front();
    		q.pop();
    		dis.pop();
    		for (int i=1;i<=m;i++)  //美剧每一个开关
    		{
    			int v=change(u,i);
    			if (p[v]) continue;  //判重
    			p[v]=1;
    			q.push(v);
    			dis.push(d+1);
    			if (v==(1<<n)-1)  //全部打开
    			{
    				printf("%d\n",d+1);
    				return;
    			}
    		}
    	}
    	printf("-1");
    	return;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++)
    	 for (int j=1;j<=n;j++)
    	  scanf("%d",&a[i][j]);
    	bfs();
    	return 0;
    }
    
  • 相关阅读:
    shell script入门
    perl环境配置以及Eclipse安装perl开发插件
    python注释
    Python中的sorted函数以及operator.itemgetter函数
    python 字典items和iteritems
    Python 字典(Dictionary) get()方法
    python numpy sum函数用法
    python numpy argsort函数用法
    python tile函数用法
    Shell之date用法
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998552.html
Copyright © 2011-2022 走看看