Poj 3037 Skiing

Skiing
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3051   Accepted: 844   Special Judge

Description

Bessie and the rest of Farmer John's cows are taking a trip this winter to go skiing. One day Bessie finds herself at the top left corner of an R (1 <= R <= 100) by C (1 <= C <= 100) grid of elevations E (-25 <= E <= 25). In order to join FJ and the other cows at a discow party, she must get down to the bottom right corner as quickly as she can by travelling only north, south, east, and west. 

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

* Line 1: Three space-separated integers: V, R, and C, which respectively represent Bessie's initial velocity and the number of rows and columns in the grid. 

* Lines 2..R+1: C integers representing the elevation E of the corresponding location on the grid.

Output

A single number value, printed to two exactly decimal places: the minimum amount of time that Bessie can take to reach the bottom right corner of the grid.

Sample Input

1 3 3
1 5 3
6 3 5
2 4 3

Sample Output

29.00

Hint

Bessie's best route is: 
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;
}



你可能感兴趣的:(Poj 3037 Skiing)