zoukankan      html  css  js  c++  java
  • [HDOJ5094] Maze (记忆化搜索,BFS,状态压缩)

    题目链接:https://vjudge.net/problem/HDU-5094

    题意:很典型的迷宫寻路,但是点与点之间有障碍或者门,每个点有钥匙。与其他题不同的地方是障碍不是单纯的某一个点不可以走,而是两点之间。求从一点出发到另一点最短路。

    很简单,用G[][][][]存两个点之间的障碍(图大了其实也可以用unordered_map<pii,pii>)。钥匙顶多10把,用位压记录钥匙状态,bfs的时候队内节点维护当前点、钥匙拥有情况、最短路。直接记忆化搞就是了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 55;
     5 const int dx[5] = {0, 0, 1, -1};
     6 const int dy[5] = {1, -1, 0, 0};
     7 typedef struct Node {
     8     int x, y, k;
     9     Node() {}
    10     Node(int x, int y, int k) : 
    11       x(x), y(y), k(k) {}
    12 }Node;
    13 typedef pair<Node, int> pni;
    14 
    15 int G[maxn][maxn][maxn][maxn];
    16 int key[maxn][maxn];
    17 int dp[1<<10][maxn][maxn];
    18 int n, m, p, k, g;
    19 int x1, y1, x2, y2;
    20 
    21 bool ok(int x, int y) {
    22     return x >= 1 && x <= n && y >= 1 && y <= m;
    23 }
    24 
    25 int bfs() {
    26     queue<pni> q;
    27     memset(dp, -1, sizeof(dp));
    28     q.push(pni(Node(1, 1, 0), 0));
    29     dp[0][1][1] = 0;
    30     while(!q.empty()) {
    31         pni tmp = q.front(); q.pop();
    32         x1 = tmp.first.x, y1 = tmp.first.y; k = tmp.first.k;
    33         if(x1 == n && y1 == m) return tmp.second;
    34         for(int i = 0; i < 4; i++) {
    35             x2 = x1 + dx[i];
    36             y2 = y1 + dy[i];
    37             if(!ok(x2, y2) || !G[x1][y1][x2][y2]) continue;
    38             if(G[x1][y1][x2][y2] != -1) {
    39                 if(!((1 << (G[x1][y1][x2][y2]) - 1) & k)) continue;
    40             }
    41             int st = k | key[x2][y2];
    42             if(dp[st][x2][y2] == -1) {
    43                 dp[st][x2][y2] = tmp.second + 1;
    44                 q.push(pni(Node(x2, y2, st), tmp.second+1));
    45             }
    46         }
    47     }
    48     return -1;
    49 }
    50 
    51 int main() {
    52     // freopen("in", "r", stdin);
    53     while(~scanf("%d%d%d",&n,&m,&p)) {
    54         scanf("%d", &k);
    55         memset(G, -1, sizeof(G));
    56         memset(key, 0, sizeof(key));
    57         for(int i = 0; i < k; i++) {
    58             scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
    59             G[x1][y1][x2][y2] = G[x2][y2][x1][y1] = g;
    60         }
    61         scanf("%d", &k);
    62         for(int i = 0; i < k; i++) {
    63             scanf("%d%d%d",&x1,&y1,&g);
    64             key[x1][y1] |= (1 << (g - 1));
    65         }
    66         cout << bfs() << endl;
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    Python(2.7.6) 特殊方法
    Python(2.7.6) 列表推导式
    代码神注释鉴赏,喜欢拿去用
    为什么说重启能解决90%的问题
    为什么说重启能解决90%的问题
    编程语言简史
    编程语言简史
    Shell脚本中循环select命令用法笔记
    程序员职业规划
    程序员职业规划
  • 原文地址:https://www.cnblogs.com/kirai/p/6785318.html
Copyright © 2011-2022 走看看