[HDU] 1180 诡异的楼梯-个人觉得比较有趣的广搜索
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1180
方法:此题和一般的地图广搜差不多,唯一的变化就是在楼梯那里,楼梯那里考虑的方式如下:
1.根据楼梯的初始状态和当时达到楼梯旁边的位置时走的时间来确定这个时候楼梯的方向。
2.再根据当时前进的方向 和 当时楼梯的方向确定走过去要多少的时间,是用1还是2.
3.不管走过去后时间是多少,如果过去后发现是障碍物或已经去过了,则该位置不进队列,不考虑从该位置开始的一个广搜。
4.如果可以从楼梯过去的那个位置进行广搜,那么该位置开始广受的广搜索不能再经过刚才才经过的楼梯,要判断这个信息不能简单通过设置visited变量,因为很多路径都有可能经过该楼梯。本代码中用一个4维数组来标记到达每一个位置有没有刚走过什么楼梯。laddUserd[x][y][u][w] =true 表示到达(x ,y)的最短路径刚经过了 (u,w)处的电梯,所以在(x,y)如果探寻到了楼梯,可以一下就判断出是不是刚走过这段楼梯,这样避免无谓的搜索。
感想:简单有趣的广搜。
代码:
View Code
#include <iostream> #include <queue> using namespace std; int m,n; char map[22][22]; char obstacle ='*'; char road = '.'; char v_ladder='|'; char h_ladder='-'; char start ='S'; char target='T'; bool visited[22][22]; int deriction[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; struct status { int x; int y; int currentTime; }; struct cmp { bool operator()(status x,status y) { if(x.currentTime > y.currentTime) return true; return false; } }; bool canGo(int x,int y) { return !visited[x][y] && map[x][y]!=obstacle; } bool laddUsed[21][21][21][21]; void BFSSearch(int x,int y) { priority_queue<status,vector<status>,cmp> q; status st_status; st_status.x=x; st_status.y=y; st_status.currentTime=0; q.push(st_status); while(!q.empty()) { status t_status = q.top(); q.pop(); if(!visited[t_status.x][t_status.y]) { visited[t_status.x][t_status.y] = true; if(map[t_status.x][t_status.y]==target) { cout<<t_status.currentTime<<endl; break; } int n_x,n_y; for(int i =0;i<4;i++) { n_x = t_status.x+deriction[i][0]; n_y = t_status.y+deriction[i][1]; if(canGo(n_x,n_y)) { status n_status; n_status.x=n_x; n_status.y=n_y; n_status.currentTime = t_status.currentTime; if(map[n_x][n_y] == road || map[n_x][n_y] == target) { n_status.currentTime ++; q.push(n_status); } else if(!laddUsed[t_status.x][t_status.y][n_x][n_y]) { if(i==1 || i==3)//vertical orientation { if(map[n_x][n_y]==v_ladder) n_status.currentTime += n_status.currentTime%2 == 0 ? 1:2; else if(map[n_x][n_y]==h_ladder) n_status.currentTime += n_status.currentTime%2 == 1 ? 1:2; if(canGo(n_x+deriction[i][0],n_y)) { n_status.x+=deriction[i][0]; q.push(n_status); laddUsed[n_status.x][n_status.y][n_x][n_y]=true; } } else if(i==0 || i==2)//horizontal orientation { if(map[n_x][n_y]==h_ladder) n_status.currentTime += n_status.currentTime%2 == 0 ? 1:2; else if(map[n_x][n_y]==v_ladder) n_status.currentTime += n_status.currentTime%2 == 1 ? 1:2; if(canGo(n_x,n_y+deriction[i][1])) { n_status.y+=deriction[i][1]; q.push(n_status); laddUsed[n_status.x][n_status.y][n_x][n_y]=true; } } } } } } } } void main() { int startX,startY; while(scanf("%d %d",&m,&n) != EOF) { if(m!=0 && n!=0) { memset(map,obstacle,sizeof(map)); memset(visited,false,sizeof(visited)); memset(laddUsed,false,sizeof(laddUsed)); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) { cin>>map[i][j]; if(map[i][j]==start) { startX = i; startY = j; } } BFSSearch(startX,startY); } } }