您的位置:首页 > 其它

hdu 1180 诡异的楼梯(BFS)

2014-08-06 23:12 295 查看

诡异的楼梯

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 8913 Accepted Submission(s): 2205


[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

地图如下:



就是遇到楼梯如果对面的已经访问过,就不用走了,如果对面的没有访问过,如果能直接过,能一下子走2格,如果不能直接过,等楼梯移过来,因为这样时间跟走过去相同,

也不会多。

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
using namespace std;
#define maxn 25
char mp[maxn][maxn];
int vis[maxn][maxn], M, N, sx, sy, tx, ty, ans;
int dir[4][2] = {{0,1}, {0,-1}, {-1,0},{1,0}}; //4个方向
struct node{
int x, y, t;
};
bool judge(int x, int y){
if(x >= 0 && x < M && y >= 0 && y < N && mp[x][y] != '*' && !vis[x][y]) return 1;
return 0;
}
bool judgeBridge(int x, int y, int t, int dir){ //注意这里要算前一秒的!!!!因为还没走
if(mp[x][y] == '|') //如果一开始是竖的话
{
if(t%2==0 && (dir == 2 || dir == 3)) //如果还是竖的,且走的也是竖的
return 1 ;
else if(t%2 && (dir == 0 || dir == 1)) //如果是横的而且走的也是横的,
return 1 ;
}
else if(mp[x][y] == '-')  //如果一开始是横的话
{
if(t%2==0 && (dir == 0 || dir == 1))  //如果还是横的,且走的也是横的
return 1;
else if(t%2 && (dir == 2 || dir == 3))
return 1;
}
return 0;
}
node q[maxn*maxn];
int BFS(int sx, int sy){
memset(vis, 0, sizeof(vis));
int front = 0, rear = 1;
q[front].x = sx; q[front].y = sy; q[front].t = 0;
vis[sx][sy] = 1;
while(front < rear){
int x = q[front].x;
int y = q[front].y;
int t = q[front].t;
front++;
if(x == tx && y == ty) return t;  //如果已经到了终点,跳出
for(int i = 0; i < 4; i++){
int nx = x+dir[i][0];
int ny = y+dir[i][1];
if(judge(nx, ny)){
if(mp[nx][ny] == '.'){
vis[nx][ny] = 1;
node temp;
temp.x = nx;
temp.y = ny;
temp.t = t+1;
q[rear++] = temp;
}
else{
int nnx = nx + dir[i][0];
int nny = ny + dir[i][1]; //过桥
if(judge(nnx, nny)){ //如果桥对面的点没有访问过的话
if(judgeBridge(nx, ny, t,i )){ //过桥
vis[nnx][nny] = 1;
node temp;
temp.x = nnx;
temp.y = nny;
temp.t = t+1;
q[rear++] = temp;
}
else{       //等待
node temp;
temp.x = x;
temp.y = y;
temp.t = t+1;
q[rear++] = temp;
}
}
}
}
}

}
return -1;
}
int main(){
while(~scanf("%d%d", &M, &N)){
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
cin>>mp[i][j];
}
}
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
if(mp[i][j] == 'S'){
mp[i][j] = '.';
sx = i; sy = j;
}
if(mp[i][j] == 'T'){
mp[i][j] ='.';
tx = i; ty = j;
}
}
}

ans = BFS(sx, sy);
printf("%d\n", ans);
}

return 0;
}


根据这题来个BFS模板吧

int bfs(int sx,int sy) //初始位置
{
memset(vis, 0 ,sizeof(vis));                            //清空访问数组
int head = 0,tail=1;                                //头是0, 尾是1, 因为要加入一个数,就是初始位置
que[head].x=sx ,que[head].y=sy ,que[head].step = 0; //把初始位置加入队列。
vis[sx][sy] = 1 ;                                   //初始位置标记已经访问过
while(head < tail)                                  //当队列不为空的时候
{
int x = que[head].x;
int y = que[head].y;
int step = que[head].step;  //拿出队首元素
head++ ;                    //弹出
if(x == ex && y == ey)      //如果已经走到终点,退出循环
{
return step ;
}
//如果没有结束
for(int i = 0 ; i < 4 ;i++){  //走上下左右4个方向
int nx = x+d[i][0]
int ny = y+d[i][1] ;
if(judge(nx, ny)){       //判断满足的条件 ,如果可以走
if(map[nx][ny] == '.'){ //如果不是楼梯直接入列
vis[nx][ny] = 1 ;   //标记已经访问过
que[tail].x = nx ;
que[tail].y = ny ;
que[tail].step = step+1 ;
tail++;             //加入队列
}
else//如果是楼梯
{
int nnx = nx + d[i][0] , nny = ny + d[i][1] ;
//楼梯对面的点没有访问过
if(judge(nnx, nny))
{
if(goStair(nx, ny, step,i))
//判断楼梯此时是否可走
{
//如果可走则直接将该点放入队列,标记为已访问
vis[nnx][nny] = 1;
que[tail].x = nnx ;
que[tail].y = nny;
que[tail].step = step+1 ;
tail++ ;
}
else
{
//如果此时楼梯不能走,则将此时所在的点放回队尾(等待)
que[tail].x = x ;
que[tail].y = y ;
que[tail].step = step+1 ;
tail++ ;
}
}
}
}
}
}
return -1 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: