hdu 1180:诡异的楼梯(BFS广搜)
2014-01-16 12:20
375 查看
诡异的楼梯
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 7642 Accepted Submission(s): 1830
[align=left]Problem Description[/align]
Hogwarts正式开学以后,Harry发现在Hogwarts里,某些楼梯并不是静止不动的,相反,他们每隔一分钟就变动一次方向.
比如下面的例子里,一开始楼梯在竖直方向,一分钟以后它移动到了水平方向,再过一分钟它又回到了竖直方向.Harry发现对他来说很难找到能使得他最快到达目的地的路线,这时Ron(Harry最好的朋友)告诉Harry正好有一个魔法道具可以帮助他寻找这样的路线,而那个魔法道具上的咒语,正是由你纂写的.
[align=left]Input[/align]
测试数据有多组,每组的表述如下:
第一行有两个数,M和N,接下来是一个M行N列的地图,'*'表示障碍物,'.'表示走廊,'|'或者'-'表示一个楼梯,并且标明了它在一开始时所处的位置:'|'表示的楼梯在最开始是竖直方向,'-'表示的楼梯在一开始是水平方向.地图中还有一个'S'是起点,'T'是目标,0<=M,N<=20,地图中不会出现两个相连的梯子.Harry每秒只能停留在'.'或'S'和'T'所标记的格子内.
[align=left]Output[/align]
只有一行,包含一个数T,表示到达目标的最短时间.
注意:Harry只能每次走到相邻的格子而不能斜走,每移动一次恰好为一分钟,并且Harry登上楼梯并经过楼梯到达对面的整个过程只需要一分钟,Harry从来不在楼梯上停留.并且每次楼梯都恰好在Harry移动完毕以后才改变方向.
[align=left]Sample Input[/align]
5 5 **..T **.*. ..|.. .*.*. S....
[align=left]Sample Output[/align]
7
Hint
Hint
地图如下:
![](http://acm.hdu.edu.cn/data/images/C6-1003.gif)
[align=left]Source[/align]
Gardon-DYGG Contest 1
[align=left]Recommend[/align]
JGShining | We have carefully selected several similar problems for you: 1072 1026 1240 1253 1242
bfs广搜。
在广搜的基础框架之上加了一个“会旋转的楼梯”,楼梯有2个初始状态 “|” 和 “-” ,每移动一次楼梯就变化一次(| => - ; - => |)。每移动一次用时一分钟,如果遇到楼梯时,正好能通过,则直接跳到楼梯对面,时间+1(也就是说2个格子只用了1分钟);如果恰好不能通过,则在原地等待1分钟。问从初始位置(S)到终点(T)的最短时间。
这道题的重点是遇到楼梯的处理,可以先用遇到楼梯时的步数(step)来判断,然后用遇到楼梯时的方向(i)来判断。
处理方法如下:
if | //遇到的楼梯初始是‘|’ if step是奇数,变化 if i 是奇数 不能通过 else 能通过 else //不变 if i 是奇数 能通过 else 不能通过 if - //遇到的楼梯初始是‘-’ if step是奇数,变化 if i 是奇数 能通过 else 不能通过 else //不变 if i 是奇数 不能通过 else 能通过
另外注意两点:
1.剪枝。有一个可以剪枝的地方:遇到楼梯先判断楼梯对面是否走过,如果已经走过,直接退出本次循环。
2.超时问题。一定要处理好step(遇到楼梯时的步数),因为step是会变的,所以这次如果不能通过,下次也一定能通过。像我一开始把“step”整成了不会变的,测试结果对了,提交却一直超时。
[b]代码:[/b]
#include <iostream> #include <queue> #include <string.h> using namespace std; char a[21][21]; bool isw[21][21]; int dx[4] = {0,1,0,-1}; int dy[4] = {1,0,-1,0}; int M,N; int startx,starty; bool pass; //能否通过梯子 struct NODE{ int x; int y; int step; }; int abs(int n) { return n>0?n:-n; } bool judge(int x,int y,int i,int step) { if( x<1 || y<1 || x>M ||y>N ) //越界 return 1; if( isw[x][y] ) //走过了 return 1; if( a[x][y]=='*' ) //遇到墙 return 1; if( a[x][y]=='|' ){ if( isw[x+dx[i]][y+dy[i]] ) return 1; if( step%2 ){ //奇,变 if( i%2 ) //奇数 pass = false; //不可以通过 else pass = true; //可以通过 } else { //不变 if( i%2 ) //奇数 pass = true; //可以通过 else pass = false; //不可以通过 } } else if( a[x][y]=='-' ){ if( isw[x+dx[i]][y+dy[i]] ) return 1; if( step%2 ){ //奇,变 if( i%2 ) //奇数 pass = true; //可以通过 else pass = false; //不可以通过 } else{ //不变 if( i%2 ) //奇数 pass = false; //不可以通过 else pass = true; //可以通过 } } return 0; } int bfs(int x,int y) { queue <NODE> q; NODE cur,next; cur.x = x; cur.y = y; cur.step = 0; q.push(cur); //第一个节点入队 while(!q.empty()){ //队首出队 cur = q.front(); q.pop(); if(a[cur.x][cur.y]=='T') //如果这一步已经走到了终点,则输出走到这一步的步数 return cur.step; for(int i=0;i<4;i++){ //下一层节点入队 int nx = cur.x + dx[i]; int ny = cur.y + dy[i]; if( judge(nx,ny,i,cur.step) ) //判定这一步可走否 continue; if(a[nx][ny]=='|' || a[nx][ny]=='-'){ //如果这一步是碰到梯子的 if(pass){ //可以通过梯子 nx += dx[i]; ny += dy[i]; } else{ //不可以通过梯子 nx -= dx[i]; ny -= dy[i]; } } next.x = nx; //可走,记录下一步的位置 next.y = ny; next.step = cur.step + 1; //可走,步数累加 isw[next.x][next.y] = true; //可走,标记走过 q.push(next); } } } int main() { while(cin>>M>>N){ for(int i=1;i<=M;i++) for(int j=1;j<=N;j++){ cin>>a[i][j]; if(a[i][j]=='S'){ startx = i; starty = j; } } memset(isw,0,sizeof(isw)); isw[startx][starty] = true; cout<<bfs(startx,starty)<<endl; } return 0; }
Freecode : www.cnblogs.com/yym2013
相关文章推荐
- HTML5画布绘图方程
- Spring工具包下载地址和方法
- java web 项目如何获取客户端登录帐号信息(用于SSO或其他)
- 软件测试需要学习些什么技能
- 计算机视觉、机器学习相关领域论文和源代码大集合
- 深入C++的new
- 敏捷开发艺术 阅读笔记
- hdu 1385 Minimum Transport Cost (最小字典序最短路径)
- iOS 中KVO和KVC的使用
- 语言字符串 语言代码
- uhttpd 重启命令
- Linux Crontab 用法详解【转】
- Win7 64位下的firefox 无法访问https的解决方法!
- ios Crash Log 分析汇总
- hibernate安装和配置和第一个Hibernate应用
- 6、坐标和依赖
- tortoiseSVN搭建Windows SVN服务器详解
- SQL Server 日志配置问题
- 西莫电机论坛
- 寒假瞎想