Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 3051 | Accepted: 844 | Special Judge |
Description
Bessie starts out travelling at a initial speed V (1 <= V <= 1,000,000). She has discovered a remarkable relationship between her speed and her elevation change. When Bessie moves from a location of height A to an adjacent location of eight B, her speed is multiplied by the number 2^(A-B). The time it takes Bessie to travel from a location to an adjacent location is the reciprocal of her speed when she is at the first location.
Find the both smallest amount of time it will take Bessie to join her cow friends.
Input
* Lines 2..R+1: C integers representing the elevation E of the corresponding location on the grid.
Output
Sample Input
1 3 3 1 5 3 6 3 5 2 4 3
Sample Output
29.00
Hint
Start at 1,1 time 0 speed 1
East to 1,2 time 1 speed 1/16
South to 2,2 time 17 speed 1/4
South to 3,2 time 21 speed 1/8
East to 3,3 time 29 speed 1/4
练习赛上的一道题:开始想的是用两个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;
}