• Luogu P4011 孤岛营救问题


    题目链接 (Click) (Here)

    注意坑点:一个地方可以有多把钥匙。

    被卡了一会,调出来发现忘了取出来实际的数字,直接把二进制位或上去了(TwT),其他的就是套路的分层图最短路。不算太难。

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, m, p, k, s;
    int can[11][11][11][11], key[11];
    int mv[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    
    int node (int x, int y, int f) {
    	return f * n * m + (x - 1) * m + y;
    }
    
    bool in_map (int x, int y) {
    	return 1 <= x && x <= n && 1 <= y && y <= m;
    }
    
    const int N = 1000010;
    const int M = 4000010;
    
    int cnt, head[N];
    const int INF = 0x3f3f3f3f;
    
    struct edge {
    	int nxt, to, w;
    	edge (int _nxt = 0, int _to = 0, int _w = 0) {
    		nxt = _nxt, to = _to, w = _w;
    	}
    }e[M];
    
    void add_edge (int u, int v, int w) {
    	e[++cnt] = edge (head[u], v, w); head[u] = cnt;
    }
    
    queue <int> q;
    int vis[N], dis[N];
    
    int spfa (int s, int t) {
    	memset (dis, 0x3f, sizeof (dis));
    	vis[s] = true; dis[s] = 0; q.push (s);
    	while (!q.empty ()) {
    		int u = q.front (); q.pop ();
    		for (int i = head[u]; i; i = e[i].nxt) {
    			int v = e[i].to;
    			if (dis[v] > dis[u] + e[i].w) {
    				dis[v] = dis[u] + e[i].w;
    				if (!vis[v]) {
    					vis[v] = true;
    					q.push (v);
    				}
    			}
    		}
    		vis[u] = false;
    	}
    	return dis[t] == INF ? -1 : dis[t];
    }
    
    vector <int> have[11][11];
    
    int main () {
    	cin >> n >> m >> p >> k;
    	for (int i = 1; i <= k; ++i) {
    		static int x1, x2, y1, y2, g;
    		cin >> x1 >> y1 >> x2 >> y2 >> g;
    		if (g == 0) {
    			can[x1][y1][x2][y2] = -1;
    			can[x2][y2][x1][y1] = -1;
    		} else {
    			can[x1][y1][x2][y2] = g;
    			can[x2][y2][x1][y1] = g;
    		}
    	}
    	cin >> s;
    	for (int i = 1; i <= s; ++i) {
    		static int x, y, g;
    	    cin >> x >> y >> g;
    		have[x][y].push_back (g);
        }
    	int s = node (n, m, (1 << p)) + 1;
    	int t = node (n, m, (1 << p)) + 2;
    	for (int i = 0; i < (1 << p); ++i) {
    		memset (key, 0, sizeof (key));
    		for (int t = i, wei = 1; t != 0; t >>= 1, ++wei) {
    			key[wei] = t & 1;
    		} 
    		for (int x = 1; x <= n; ++x) {
    			for (int y = 1; y <= m; ++y) {
    				for (int t = 0; t < 4; ++t) {
    				    int tx = x + mv[t][0];
    					int ty = y + mv[t][1];
    					if (!in_map (tx, ty)) continue;
    					if (can[x][y][tx][ty] == 0 || (can[x][y][tx][ty] > 0 && key[can[x][y][tx][ty]] != 0)) {
    						// 没有门 / 有钥匙
    						// if (can[x][y][tx][ty] != 0) printf ("node (%d, %d, %d) -> node (%d, %d, %d)
    ", x, y, i, tx, ty, i);
    						add_edge (node (x, y, i), node (tx, ty, i), 1);
    					}
    				}
    				for (int t = 0; t < have[x][y].size (); ++t) {
    					if (!key[have[x][y][t]])
    						add_edge (node (x, y, i), node (x, y, (i | (1 << (have[x][y][t] - 1)))), 0);
    				}
    			}
    		}
    		add_edge (node (n, m, i), t, 0);
    	}
    	add_edge (s, node (1, 1, 0), 0);
    	cout << spfa (s, t) << endl;
    } 
    
    
  • 相关阅读:
    sql 变量赋值
    mysql 行号 获取指定行数据
    SQL Server获取指定行的数据
    sql server 创建内联表值函数
    sql server 表变量存储临时查询数据
    sql server 循环操作
    oracle for in 学习
    oracle C# 访问
    sql server insert values 多值 与oracle 的不同
    mysql 如何选择随机行
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10537889.html
Copyright © 2020-2023  润新知