Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 3051 | Accepted: 844 | Special Judge |
Description
Input
Output
Sample Input
1 3 3 1 5 3 6 3 5 2 4 3
Sample Output
29.00
Hint
练习赛上的一道题:开始想的是用两个BFS先把每个点对应速度求出来,再求出到达终点的时间。没处理好,不是WA,就是TLE。
这个题目网上很多解题报告,都用了优先队列或者最短路径什么的。不过我这个算是卡时间而过,800MS........但好歹写出来了。 广搜到每个点时,先求出该点去下个点的速度(如果遍历过了,则选择大的更新值),然后求源点到达该点时间(若遍历过,则选择时间小的)。队列为空时 则已经找到源点到达终点的最小时间值。起初认为当第一次访问了终点就可以结束了,其实最先遍历终点并不是用时最少到达终点的。要逐个选出最小值。。。。如果有优先队列的话,就更好判断了(可是不会用)。
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <cstring> #include <iomanip> using namespace std; struct Point//入队的点 { int x,y; } start,end; int map[105][105],visit[105][105],visit2[105][105],r,c;//两个visit数分别为BFS中两个部分做标志 double tim[105][105],ans[105][105];//各点到下点时间 和总时间 double vv[105][105];//各点速度 int d[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};//四个方向 bool inside(int x,int y)//判断是否越界 { if(x<0 || x>= r || y<0 || y >=c) return false; return true; } int main() { int i,j; double v,tmp,tmp1; cin >> v >> r >> c; for(i=0; i<r; i++) for(j=0; j<c; j++) { scanf("%d",&map[i][j]); } memset(tim,0,sizeof(tim)); memset(visit,0,sizeof(visit)); memset(visit2,0,sizeof(visit2)); memset(ans,0,sizeof(ans)); start.x = 0;//起点 start.y = 0; end.x = r-1;//终点 end.y = c-1; //先做好起点的处理 vv[0][0] = v; queue<Point> q; q.push(start); visit[start.x][start.y] = 1; visit2[start.x][start.y] = 1; tim[start.x][start.y] = 1.0/vv[start.x][start.y]; while(!q.empty())//队列为空就结束遍历 { Point t = q.front(); Point tt; q.pop(); //if(t.x == end.x && t.y == end.y)此处不注释便WA了 //break; for(i=0; i<4; i++) { tt.x = t.x + d[i][0]; tt.y = t.y + d[i][1]; if(inside(tt.x,tt.y)) { tmp = vv[t.x][t.y] * pow(2.0,(map[t.x][t.y] - map[tt.x][tt.y]));//下点的速度 if(visit[tt.x][tt.y] == 0)//未被遍历 { visit[tt.x][tt.y] = 1; vv[tt.x][tt.y] = tmp; } else//被遍历 选择速度大的值 { if(vv[tt.x][tt.y] < tmp) vv[tt.x][tt.y] = tmp; } tim[tt.x][tt.y] = 1.0/vv[tt.x][tt.y];//下点到达其他点时间 tmp1 = ans[t.x][t.y] + tim[t.x][t.y];//到下点的总时间 if(visit2[tt.x][tt.y] == 0)//被访问 { visit2[tt.x][tt.y] = 1; ans[tt.x][tt.y] = tmp1; q.push(tt); } else { if(ans[tt.x][tt.y] > tmp1)//未被访问 选择时间小的 { ans[tt.x][tt.y] = tmp1; q.push(tt);//再次入队 } } } } } printf("%.2f\n",ans[end.x][end.y]); return 0; }