[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 }
时间: 2024-10-10 09:34:07

[HDOJ5094] Maze (记忆化搜索,BFS,状态压缩)的相关文章

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

hdu 1514 记忆化搜索

题意是给4堆(堆的高度小于等于40)有颜色(颜色的种类小于等于20)的物品,你有一个篮子最多能装5件物品,每次从这4堆物品里面任取一件物品放进篮子里,但是取每堆物品时,必须先取上面的物品,才能取下面的物品,如果发现篮子里的两种物品的颜色一样,那么把这两种物品拿出来,问最后最多能拿出多少对物品?:解题思路:记忆化搜索+dp+状态压缩:因为40×40×40×40不会太大,所以可以用dp[x[1]][x[2]][x[3]][x[4]]记录搜索的状态:dp[x[1]][x[2]][x[3]][x[4]]

BZOJ 3139 [Hnoi2013]比赛 记忆化搜索

题意:链接略 方法:记忆化搜索 解析: 记忆化搜索,状态内部压缩起始点以及所有点目前剩下的未匹配的分值. 注意不可以用map,因为我们记忆化的目的其实是大部分消除冗余的等于0的方案. 所以就得上hash表-. 用map坑死我了. 代码: #include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 15

hdu 4597 Play Game(记忆化搜索)

题目链接:hdu 4597 Play Game 题目大意:给出两堆牌,仅仅能从最上和最下取,然后两个人轮流取,都依照自己最优的策略.问说第一个人对多的分值. 解题思路:记忆化搜索,状态出来就很水,dp[fl][fr][sl][sr][flag],表示第一堆牌上边取到fl,以下取到fr,相同sl.sr为第二堆牌,flag为第几个人在取.假设是第一个人,dp既要尽量大,假设是第二个人,那么肯定尽量小. #include <cstdio> #include <cstring> #incl

HDU 4597 Play Game(记忆化搜索,深搜)

题目 //传说中的记忆化搜索,好吧,就是用深搜//多做题吧,,这个解法是搜来的,蛮好理解的 //题目大意:给出两堆牌,只能从最上和最下取,然后两个人轮流取,都按照自己最优的策略,//问说第一个人对多的分值.//解题思路:记忆化搜索,状态出来就非常水,dp[fl][fr][sl][sr][flag],//表示第一堆牌上边取到fl,下面取到fr,同样sl,sr为第二堆牌,flag为第几个人在取.//如果是第一个人,dp既要尽量大,如果是第二个人,那么肯定尽量小. http://www.2cto.co

Doing Homework---hdu1074(状态压缩&amp;&amp;记忆化搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 有n(n<=15)门课需要做作业,每门课所需时间是used_time以及每门课作业上交的最后期限是deadline,晚交一天扣一分,现在来安排最好的写作业计划,让最终的扣除分数最少:   由于n的取值范围不大所以我们可以枚举除所有的状态进行判断是否是最优的即可,状态数为2^n-1; 我们可以用状态压缩来表示出各种状态:二进制中的第i为为1代表第i门课已经完成了. #include <cstd

hdu 4628 Pieces(状态压缩+记忆化搜索)

Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1811    Accepted Submission(s): 932 Problem Description You heart broke into pieces.My string broke into pieces.But you will recover one

ACM学习历程—ZOJ3471 Most Powerful(dp &amp;&amp; 状态压缩 &amp;&amp; 记忆化搜索 &amp;&amp; 位运算)

Description Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way

hdu4753 状态压缩dp博弈(记忆化搜索写法)

http://acm.hdu.edu.cn/showproblem.php?pid=4753 Problem Description There is a 3 by 3 grid and each vertex is assigned a number. It looks like JiuGongGe, but they are different, for we are not going to fill the cell but the edge. For instance, adding

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物