June 11th 模拟赛C T2 Cowski Solution

空降题目处
点我点我点我

Description:

Bessie和其他一些人去滑雪。Bessie发现她自己站在一块R*C(1<=R,C<=100)的区域中,区域中的每一块都有一个高度值E_ij(-25<=E_ij<=25)。为了参加大家的聚会,Bessie想要尽快到达右下角。Bessie每一步只能向正东,正西,正南,正北前进一步。Bessie以初速度V(1<=V<=1,000,000)前进,她发现了一个她的速度和高度的关系。当Bessie从高度A移动到高度B时,他的速度就乘上了一个数2^(A-B)。Bessie移动一步的速度取决于她在前一格时的速度。
请找出Bessie移动所需的最小时间。

Input

第1行:3个用空格隔开的整数:V,R,C,分别表示Bessie的初速度和区域的长度和宽度
第2 - R+1行:以矩阵的形式表示该区域中各块的高度。

Output

输出一个实数(保留2位小数),表示Bessie达到目的地最少需要的时间。

Solution

SPFA计算时间,精度至少DOUBLE(可以使用EXTENDED),注意输出精度问题(坑数据).

Program

var
    v:extended;
    s:string;
    r,c,i,j,l:longint;
    m:array [-50..50] of extended;
    p:array [1..100,1..100] of boolean;
    d:array [1..400000,1..2] of longint;
    e:array [0..101,0..101] of longint;
    list:array [0..101,0..101] of extended;
    move:array [1..4,1..2] of longint=((1,0),(0,1),(-1,0),(0,-1));

procedure SPFA(x,y:longint);
var
    i,j,k:longint;

begin

    p[x,y]:=true;
    list[x,y]:=0;
    d[1,1]:=x;
    d[1,2]:=y;
    i:=0;
    j:=1;
    while i<j do
    begin
    inc(i);
        for k:=1 to 4 do
            if list[d[i,1]+move[k,1],d[i,2]+move[k,2]]>list[d[i,1],d[i,2]]+m[e[d[i,1],d[i,2]]]*v then
            begin
                list[d[i,1]+move[k,1],d[i,2]+move[k,2]]:=list[d[i,1],d[i,2]]+m[e[d[i,1],d[i,2]]]*v;
                if not p[d[i,1]+move[k,1],d[i,2]+move[k,2]] then
                begin
                    p[d[i,1]+move[k,1],d[i,2]+move[k,2]]:=true;
                    inc(j);
                    d[j,1]:=d[i,1]+move[k,1];
                    d[j,2]:=d[i,2]+move[k,2];
                end;
            end;
        p[d[i,1],d[i,2]]:=false;
    end;

end;

begin

    assign(input,'cowski.in');
    assign(output,'cowski.out');
    reset(input);
    rewrite(output);

    readln(v,r,c);
    v:=1/v;
    for i:=1 to r do
        for j:=1 to c do
        begin
            read(e[i,j]);
            if (i<>1) or (j<>1) then
                e[i,j]:=e[i,j]-e[1,1];
            list[i,j]:=11258999068426240000;
        end;
    e[1,1]:=0;
    m[0]:=1;
    for i:=1 to 50 do
    begin
        m[i]:=m[i-1]*2;
        m[-i]:=m[1-i]/2;
    end;
    SPFA(1,1);  

    str(list[r,c]:0:4,s);
    l:=length(s);
    if s[l-1]>'5' then
        list[r,c]:=list[r,c]+0.01;
    if (s[l-1]='5') and (ord(s[l-2]) mod 2=0) then
        list[r,c]:=list[r,c]+0.01;
    str(list[r,c]:0:4,s);
    delete(s,l-1,2);
    writeln(s);

    close(input);
    close(output);

end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值