HDU 1180 诡异的楼梯(广搜、优先队列)
2015-08-08 20:36
295 查看
HDU 1180 诡异的楼梯Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 10885 Accepted Submission(s): 2704Problem Description Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反, 他们每隔一分钟就变动一次方向. 比如下面的例子里,一开始楼梯在竖直方向, 一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向. Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友) 告诉Harry正好有一个魔法道具可以帮助他 寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的. Input 测试数据有多组,每组的表述如下: 第一行有两个数,M和N,接下来是一个M行N列的地图,'*'表示障碍物, '.'表示走廊,'|'或者'-'表示一个楼梯,并且标明了它在一开始时所处的位置: '|'表示的楼梯在最开始是竖直方向,'-'表示的楼梯在一开始是水平方向. 地图中还有一个'S'是起点,'T'是目标,0<=M,N<=20,地图中不会出现两个相连的梯子. Harry每秒只能停留在'.'或'S'和'T'所标记的格子内. Output 只有一行,包含一个数T,表示到达目标的最短时间. 注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟, 并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟, Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向. Sample Input 5 5 **..T **.*. ..|.. .*.*. S.... Sample Output 7 HintHint 地图如下: |
好了,废话不多说,下面就说一下这道题的解题!
这道题不难看出是一个广搜求最短路问题,关于广搜,都是那一个样子,都很难出什么大变化,广搜变来变去都是在那一个模板上修改几个变量,增减几个变量而已!
做广搜主要的就是边界条件,那就连看看边界条件是什么吧,四周边界肯定都还是原样,没有什么改变,别急,那中间那个楼梯怎么判断,遇到楼梯只要一步就可以过去了,那如果楼梯当时是处于另外一种方式呢?那就要在那等一秒了,所以秒数就要 +2 了 ,我们都知道,广搜中是按照步数的进行搜索的,那如果遇到步数 +2 的那就不能直接放入队列中,因为可能出现先判断步数大了,那该怎么办呢,这里优先队列就起到了独特的作用了,他可以将放入队列中的元素按照某一设定的排列方式排列!
这是优先队列的结构体定义方式:
struct A
{
int x,y,step;
bool operator < (const A &a) const // 对优先队列中 < 运算符进行重新定义, 按照结构体中的步数元素由小到大排序。
{
return a.step < step;
}
};
附上代码:(代码有点长,本来可以简化的,犹豫时间问题,这个任务就交给大家了!)
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <queue> using namespace std; int visit[50][50]; // 用来标记该点是否被搜索过 char str[50][50]; int d[4][2] = {-1,0,1,0,0,1,0,-1}; // 上下右左 四个方向的坐标变化 int n,m; struct A { int x,y,step; bool operator < (const A &a) const { return a.step < step; } }; int bfs(int x1,int y1,int x2,int y2) { int sx,sy; priority_queue<A> Q; A e; e.x = x1; e.y = y1; e.step = 0; Q.push(e); visit[x1][y1] = 1; // 该地点被搜索过标记为 1 while(!Q.empty()) { e = Q.top(); if(e.x == x2 && e.y == y2) // 如果寻找到目标,则搜索结束! break; Q.pop(); for(int i = 0; i < 4; i++) // 向四个方向搜索! { sx = e.x + d[i][0]; sy = e.y + d[i][1]; if(sy >= 0 && sy < n && sx >= 0 && sx < m && (str[sx][sy] == '.' || str[sx][sy] == 'T' )&& visit[sx][sy] == 0) { A e1; e1.x = sx; e1.y = sy; e1.step = e.step + 1; Q.push(e1); visit[sx][sy] = 1; } if(sy >= 0 && sy < n && sx >= 0 && sx < m && str[sx][sy] == '|' ) { if(e.y == sy && e.x < sx && (str[sx + 1][sy] == '.' || str[sx + 1][sy] == 'T' ) && visit[sx + 1][sy] == 0 && sx + 1 < m) { A e1; e1.x = sx + 1; e1.y = sy; if(e.step % 2 == 0) e1.step = e.step + 1; // 桥是直接可以过的 else e1.step = e.step + 2; // 桥不可以直接过,等一秒 Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y == sy && e.x > sx && (str[sx - 1][sy] == '.' || str[sx - 1][sy] == 'T' ) && visit[sx - 1][sy] == 0 && sx - 1 >= 0) { A e1; e1.x = sx - 1; e1.y = sy; if(e.step % 2 == 0) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y < sy && e.x == sx && (str[sx][sy + 1] == '.' || str[sx][sy + 1] == 'T' ) && visit[sx][sy + 1] == 0 && sy + 1 < n) { A e1; e1.x = sx; e1.y = sy + 1; if(e.step % 2 == 1) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y > sy && e.x == sx && (str[sx][sy - 1] == '.' || str[sx][sy - 1] == 'T' ) && visit[sx][sy - 1] == 0 && sy - 1 >= 0) { A e1; e1.x = sx; e1.y = sy - 1; if(e.step % 2 == 1) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } } if(sy >= 0 && sy < n && sx >= 0 && sx < m && str[sx][sy] == '-') { if(e.y == sy && e.x < sx && (str[sx + 1][sy] == '.' || str[sx + 1][sy] == 'T' )&& visit[sx + 1][sy] == 0 && sx + 1 < m) { A e1; e1.x = sx + 1; e1.y = sy; if(e.step % 2 == 1) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y == sy && e.x > sx && (str[sx - 1][sy] == '.' || str[sx - 1][sy] == 'T' ) && visit[sx - 1][sy] == 0 && sx - 1 >= 0) { A e1; e1.x = sx - 1; e1.y = sy; if(e.step % 2 == 1) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y < sy && e.x == sx && (str[sx][sy + 1] == '.' || str[sx][sy + 1] == 'T') && visit[sx][sy + 1] == 0 && sy + 1 < n) { A e1; e1.x = sx; e1.y = sy + 1; if(e.step % 2 == 0) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } if(e.y > sy && e.x == sx && (str[sx][sy - 1] == '.' || str[sx][sy - 1] == 'T' ) && visit[sx][sy - 1] == 0 && sy - 1 >= 0) { A e1; e1.x = sx; e1.y = sy - 1; if(e.step % 2 == 0) e1.step = e.step + 1; else e1.step = e.step + 2; Q.push(e1); visit[e1.x][e1.y] = 1; } } } } if(Q.empty()) return -1; // 找不到则返回 -1 ,这一题中没有这种情况,可以省去! else { while(!Q.empty()) // 每次搜索结束后清空队列 Q.pop(); return e.step; } } int main() { while(cin >> m >> n) { getchar(); memset(visit,0,sizeof(visit)); // 每次搜索前赋值为 0,记为没有被搜索过 memset(str,'\0',sizeof(str)); // 清空字符串 str int beginx,beginy,endx,endy; for(int i = 0; i < m; i++) { scanf("%s",str[i]); for(int j = 0; j < n; j++) { if(str[i][j] == 'S') { beginx = i; // 记录其实位置 beginy = j; } if(str[i][j] == 'T') { endx = i; // 记录终点位置 endy = j; } } } int ans = bfs(beginx,beginy,endx,endy); cout << ans << endl; } return 0; }
相关文章推荐
- Windows下一个SlikSVN使用
- 使用c/c++扩展python
- Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置
- linux下的io多路复用形象化理解
- Android中关于键盘的操作
- UIButton的一些常用知识点
- 应届生自我介绍模板
- Apache + Tomcat 负载均衡 session复制
- hdu 5361 In Touch 最短路(set+搜索实现)
- Sum Root to Leaf Numbers
- 配色方式
- JDBC连接mysql
- 杭电ACM 1008Elevator
- 数组越界的内存分配
- 在linux系统中,如果忘记了MySQL的root密码,有没有办法重新设置新密码呢?
- 3.5html学习笔记之框模型,盒子模型
- Java基础知识点总结
- POJ3641(Pseudoprime numbers 费马小定理)
- leetcode之二叉树的镜像
- isc-dhcp-server