hdu 杭电1429 胜利大逃亡(续)
题目表述
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。输入
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:
. 代表路
* 代表墙
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J
每组测试数据之间有一个空行。输出
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。
不难看出,本题是一道搜索,而且本题需要记录钥匙的携带情况以判断门是否可以通过的问题
但是,有10种钥匙,这使维度处理变得困难(因为就算是开了10个维度记录钥匙也不能直接让某个维度改变,因为c++里就没有这种操作)
所以使用状态压缩
把10把钥匙的携带状态用一个二进制的数字记录下来(程序里用10进制整形变量表示)
例:第0位记录钥匙a的携带状态,0代表没有,1代表有。以此类推。
这样就可以带着10把钥匙的状态进行搜索了。
当遇到一把钥匙时:找到钥匙对应的位,然后和当前状态取“位或”操作就相当于捡起了这把钥匙
(位或:即按位取或,有1就得1,都不是1就得0)
例:当前状态有钥匙b,e;要捡起钥匙j
所以当前的状态:
a | b | c | d | e | f | g | h | i | j |
0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
在程序里就是18(2 ^ 1 + 2 ^ 4)
现在要捡起的钥匙j就是512(其他位置都是0,第九位是1)
a | b | c | d | e | f | g | h | i | j |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
两个二进制数字取位或之后
a | b | c | d | e | f | g | h | i | j |
0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
这样就算是捡起了钥匙。
同理,当遇到门时,判断是否有这个门对应的钥匙时
算出门对应的二进制数字,和当前状态取“位与”操作后,看得数是否为零,为零就是没有对应的钥匙。
(位与:按位取“与”,都为1得1,否则为0)
关于广搜:
先判断当前状态,再看能不能去,一定要有条理,否则会很乱。
并且广搜第一次到一个地方时一定是最小的步数(但深搜不是),所以再加个判断就行了
#include <iostream>
#include <cstring>
#include <queue>using namespace std;char a[25][25];
int n, m, t;
int f[25][25][2048];
int sx, sy;
int addx[5] = {0, -1, 0, 1, 0};
int addy[5] = {0, 0, 1, 0, -1};struct point
{int x;int y;int state;
};queue <point> q;int bfs()
{int size;point g, h;g.x = sx;g.y = sy;g.state = 0;f[g.x][g.y][g.state] = 0;q.push(g);while (q.size()){g = q.front();q.pop();for (int i = 1; i <= 4; i++){h.x = g.x + addx[i];h.y = g.y + addy[i];h.state = g.state;if (a[h.x][h.y] == '*')continue;if (a[h.x][h.y] >= 'a' && a[h.x][h.y] <= 'j') //捡钥匙,状态要变{size = a[h.x][h.y] - 'a'; h.state = g.state | (1 << size);}if (((a[h.x][h.y] >= 'a' && a[h.x][h.y] <= 'z') || a[h.x][h.y] == '.' || (a[h.x][h.y] >= 'A' && a[h.x][h.y] <= 'J' && (h.state & (1 << (a[h.x][h.y] - 'A'))) != 0)) //是钥匙 或者 路 或者 有对应钥匙能打开的门,但是一定要没去过&& f[h.x][h.y][h.state] == -1){f[h.x][h.y][h.state] = f[g.x][g.y][g.state] + 1;q.push(h);}if (a[h.x][h.y] == '^')if (f[g.x][g.y][g.state] + 1 < t)return f[g.x][g.y][g.state] + 1;elsereturn -1;}}return -1;
}int main()
{int i, j;while (cin >> n >> m >> t){memset(f, -1, sizeof(f));while (q.size())q.pop();for (i = 0; i <= n + 1; i++)for (j = 0; j <= m + 1; j++)a[i][j] = '*';for (i = 1; i <= n; i++)for (j = 1; j <= m; j++){cin >> a[i][j];if (a[i][j] == '@'){sx = i;sy = j;a[i][j] = '.';}}cout << bfs() << endl;}return 0;
}
hdu 杭电1429 胜利大逃亡(续)相关推荐
- HDU 1429 胜利大逃亡(续) (BFS+位压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) ...
- BFS——1429 胜利大逃亡(续)
1429 胜利大逃亡(续) 文章目录 1429 胜利大逃亡(续) 题意: 思路: 本题的重点在于标记数组,除了基本的坐标 ( x , y ) (x,y) (x,y)以外,在同一位置是否有某个钥匙显然会 ...
- HDU 1429 胜利大逃亡(续)
胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdu 1429 胜利大逃亡(续) bfs+状态压缩
胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU - 1429 胜利大逃亡(续) (BFS+状压)
题目链接 思路 因为新拿到一把钥匙所以相同位置可以重复走,一共10把钥匙二进制表示拿到的钥匙,判断下个位置是否可以走. #include <bits/stdc++.h> const int ...
- hdu 1429 胜利大逃亡(续)
状态压缩+宽搜 #include<cstdio> #include<iostream> #include<cstring> #include<queue> ...
- HDOJ1429(胜利大逃亡(续))
胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU-1429 胜利大逃亡(续)
A - 胜利大逃亡(续) Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- (HDU1429)胜利大逃亡(续)-BFS-状态压缩
胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
最新文章
- ASP.NET中数据库数据导入Excel并打印
- 快速排序,冒泡排序时间复杂度推导
- 漫游Kafka设计篇之消息传输的事务定义
- linux---基础03
- Oracle 获取表注释和列注释
- ImageLoader的简单分析
- 性能测试:竞品APP性能对比测试
- 在html用vue组件,html页面引入vue组件
- 时间或许从未流逝,而人在氧化新陈代谢与日升日落中,以自己为坐标,定义了时间!...
- html如何设置导航栏例子,CSS 导航栏
- 谷歌 draco学习 二 压缩点信息
- Censored! :ac自动机 + DP
- 0基础如何用几分钟学会视频剪辑
- 计算机缓存加速网络,教你win7怎么清理缓存为电脑提速
- 解决问题:cv::Exception,位于内存位置 0x000000D2956FE120 处
- 基于Android的火灾报警
- android remoteViews
- 【转】获取用户移动方向,指南针原理
- 设计模式 -- 面向对象设计原则、黑箱/白箱复用
- VR与智能家居有哪些可能的结合形式?可为智能家居带来哪些好处?