题目表述
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 胜利大逃亡(续)相关推荐

  1. HDU 1429 胜利大逃亡(续) (BFS+位压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)  ...

  2. BFS——1429 胜利大逃亡(续)

    1429 胜利大逃亡(续) 文章目录 1429 胜利大逃亡(续) 题意: 思路: 本题的重点在于标记数组,除了基本的坐标 ( x , y ) (x,y) (x,y)以外,在同一位置是否有某个钥匙显然会 ...

  3. HDU 1429 胜利大逃亡(续)

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  4. hdu 1429 胜利大逃亡(续) bfs+状态压缩

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  5. HDU - 1429 胜利大逃亡(续) (BFS+状压)

    题目链接 思路 因为新拿到一把钥匙所以相同位置可以重复走,一共10把钥匙二进制表示拿到的钥匙,判断下个位置是否可以走. #include <bits/stdc++.h> const int ...

  6. hdu 1429 胜利大逃亡(续)

    状态压缩+宽搜 #include<cstdio> #include<iostream> #include<cstring> #include<queue> ...

  7. HDOJ1429(胜利大逃亡(续))

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  8. HDU-1429 胜利大逃亡(续)

    A - 胜利大逃亡(续) Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit ...

  9. (HDU1429)胜利大逃亡(续)-BFS-状态压缩

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

最新文章

  1. ASP.NET中数据库数据导入Excel并打印
  2. 快速排序,冒泡排序时间复杂度推导
  3. 漫游Kafka设计篇之消息传输的事务定义
  4. linux---基础03
  5. Oracle 获取表注释和列注释
  6. ImageLoader的简单分析
  7. 性能测试:竞品APP性能对比测试
  8. 在html用vue组件,html页面引入vue组件
  9. 时间或许从未流逝,而人在氧化新陈代谢与日升日落中,以自己为坐标,定义了时间!...
  10. html如何设置导航栏例子,CSS 导航栏
  11. 谷歌 draco学习 二 压缩点信息
  12. Censored! :ac自动机 + DP
  13. 0基础如何用几分钟学会视频剪辑
  14. 计算机缓存加速网络,教你win7怎么清理缓存为电脑提速
  15. 解决问题:cv::Exception,位于内存位置 0x000000D2956FE120 处
  16. 基于Android的火灾报警
  17. android remoteViews
  18. 【转】获取用户移动方向,指南针原理
  19. 设计模式 -- 面向对象设计原则、黑箱/白箱复用
  20. VR与智能家居有哪些可能的结合形式?可为智能家居带来哪些好处?

热门文章

  1. 常见的WebShell管理工具
  2. HTML基础DW使用教程
  3. 头条号运营技巧,百万爆文运营经验分享
  4. vue实现横向无限滚动
  5. 在阿里,我们如何管理测试环境?
  6. c语言实现陷波器算法,50Hz数字陷波器的设计.doc
  7. 基于ichartjs在android上使用HTML5实现各种图表的类库
  8. 《程序是怎么跑起来的》第一章学习笔记
  9. php 计算从开始时间到结束时间 总共有多少天
  10. 程序员都在读的实战书,你看懂封面了吗?