题意:一个地图,告诉你起点位置然后,告诉你终点位置,让你从起点出发前往终点求最短时间,地图中有4中路,第一种是墙,不能走,第二种是树,需要花费Tt的时间才能通过,第三种是沙子,需要花费Ts的时间才能通过,第四种是路径,需要花费Tp的时间才能通过。
想法:从起点开始进行广搜,这种情况的广搜搜图计算时间与其他的有所不同,因为其他的每个格子的时间是等量的,所以只要广搜第一次搜索到直接跳出,因为必定是最短路,最短路的长度就是广搜的层数。但是这个题目升级的地方就在于最短路的长度不是广搜的层数,因此,第一次遇到不能直接跳出,需要继续搜索。因为很有可能在时间的计算中层数低的但是总时间长,所以这里启用一个数组dis[x][y],表示地图中从起点出发到达(x, y)的目前来说的最短时间,一个新点被更新的条件是:在范围内,其次是新点不在石头上面,之后就是新点的时间要比dis[][]中存储的时间要小,不然更新没有意义,队列永远会有元素存在。到此问题迎刃而解,最后在队列空之后,判断终点的dis[][]是否被更新过,如果没有被更新表示无法到达目的地,输出-1,如果被更新了,那么就直接输出即可,这就是最短时间。
#include<iostream> #include<cstring> #include<queue> using namespace std; const int max_size = 22; const int inf = 0x7fffffff; int R, C; int Tp, Ts, Tt; char map[max_size][max_size]; struct node{ int x; int y; int times; }; struct node start, destination; int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1}; int addTime(char x) { if(x == 'T') return Tt; else if(x == '.') return Ts; else if(x == '#') return Tp; } int BFS() { bool visit[max_size][max_size]; int dis[max_size][max_size]; queue<node>q; while(!q.empty()) q.pop(); memset(visit, false, sizeof(visit)); for(int i = 1; i <= R; ++i){ for(int j = 1; j <= C; ++j){ dis[i][j] = inf; } } start.x++; start.y++; destination.x++; destination.y++; dis[start.x][start.y] = 0; q.push(start); while(!q.empty()){ node cur = q.front(); q.pop(); for(int k = 0; k < 4; ++k){ node nxt; nxt.x = cur.x + dir[k][0]; nxt.y = cur.y + dir[k][1]; nxt.times = cur.times + addTime(map[nxt.x][nxt.y]); if(nxt.times < dis[nxt.x][nxt.y] && nxt.x >= 1 && nxt.x <= R && nxt.y >= 1 && nxt.y <= C && map[nxt.x][nxt.y] != '@'){ dis[nxt.x][nxt.y] = nxt.times; q.push(nxt); } } } if(dis[destination.x][destination.y] == inf) return -1; else return dis[destination.x][destination.y]; } int main() { int ca = 1; while(cin>>R>>C){ cin>>Tp>>Ts>>Tt; for(int i = 1; i <= R; ++i){ cin>>map[i] + 1; } cin>>start.x>>start.y>>destination.x>>destination.y; cout<<"Case "<<ca++<<": "<<BFS()<<endl; } return 0; }