zoukankan      html  css  js  c++  java
  • [NOIP模拟赛][分层图][状态压缩] 密室

    题面

    题目描述
    (X) 正困在一个密室里,他希望尽快逃出密室。

    密室中有 (N) 个房间,初始时,小 (X)(1) 号房间,而出口在 (N) 号房间。

    密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条从房间 (X) 到房间 (Y) 的通道。另外,想要通过某个传送门,就必须具备一些种类的钥匙(每种钥匙都要有才能通过)。幸运的是,钥匙在打开传送门的封印后,并不会消失。

    然而,通过密室的传送门需要耗费大量的时间,因此,小 (X) 希望通过尽可能少的传送门到达出口,你能告诉小 (X) 这个数值吗?

    另外,小 (X) 有可能不能逃出这个密室,如果是这样,请输出 (No Solution)


    我们可以利用分层图的思想,将当前获得的钥匙有哪些作为分层的依据进行转移,
    我们发现 (k lt 10),想到可以状态压缩表示钥匙数,
    然后这题就差不多解决了

    代码:

    // 状压二进制枚举当前钥匙的状态
    // BFS 转移 Dis
    
    # include <iostream>
    # include <cstdio>
    # include <cstring>
    # include <queue>
    # define MAXN 6005
    # define MAXM 6005
    
    struct edge{
    	int v, next, key;
    }e[MAXM];
    struct node{
    	int id, key;
    };
    int hd[MAXN], cntE; int dis[MAXN]; bool inQ[1<<11][MAXN];
    int hasKey[MAXN]; // 表示每个节点有的钥匙
    // int reqKey[MAXM]; // 表示每个传送门需要的钥匙
    // if(nowKey & reqKey == reqKey) then
    int f[1<<11][MAXN];
    
    void AddE(int u, int v, int reqKey){
    	e[++cntE] = (edge){v, hd[u], reqKey};
    	hd[u] = cntE;
    }
    
    int main(){
    	int n, m, k;
    
    	scanf("%d%d%d", &n, &m, &k);
    
    	for(int i = 1; i <= n; i++){
    		for(int j = 1, x; j <= k; j++){
    			hasKey[i] <<= 1;
    			scanf("%d", &x);
    			hasKey[i] += x;
    		}
    	}
    
    	for(int i = 1, x, y, req; i <= m; i++){
    		req = 0;
    		scanf("%d%d", &x, &y);
    		for(int j = 1, xx; j <= k; j++){
    			req <<= 1;
    			scanf("%d", &xx);
    			req += xx;
    		}
    		AddE(x, y, req);
    	}
    
    	std::queue<node>Q;
    	memset(f, 0x3f, sizeof(f));
    	f[hasKey[1]][1] = 0; Q.push((node){1, hasKey[1]});
    	inQ[hasKey[1]][1] = 1;
    
    	while(Q.size()){
    		node now = Q.front(); Q.pop();
    		inQ[now.key][now.id] = 0;
    
    		for(int i = hd[now.id], nxtSta; i; i = e[i].next){
    			nxtSta = now.key | hasKey[e[i].v];
    			if((e[i].key & now.key) == e[i].key && f[nxtSta][e[i].v] > f[now.key][now.id] + 1){
    				f[nxtSta][e[i].v] = f[now.key][now.id] + 1;
    				if(!inQ[nxtSta][e[i].v]){
    					inQ[nxtSta][e[i].v] = 1;
    					Q.push((node){e[i].v, nxtSta});
    				}
    			}
    		}
    	}
    
    	int ans = 0x3f3f3f3f;
    	for(int i = 0; i < (1<<k); i++){
    		ans = std::min(ans, f[i][n]);
    	}
    
    	if(ans == 0x3f3f3f3f){
    		printf("No Solution");
    	}
    	else{
    		printf("%d", ans);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    iOS开发笔记--Layer 图层圆角、边框 、底纹其他常用操作
    tableView中deselectRowAtIndexPath的作用
    升级到XCode6后,iOS8里设置tableview的setSeparatorInset:UIEdgeInsetsZero不起作用的解决办法
    UITableView代理和数据源方法总结
    ios修改textField的placeholder的字体颜色、大小
    iOS-TextField知多少
    iOS开发SVN更新代码不报错却运行不了问题
    apache http server 局域网无法访问
    修改 apache http server 默认站点目录
    批处理 教程(转载)
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/13686923.html
Copyright © 2011-2022 走看看