T2:滑雪(cowski.pas/c/cpp)

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达到目的地最少需要的时间。

Sample Input

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

Sample Output

29.00
Hint

【样例说明】
 Bessie的最佳路径是:
(1,1) 时间 0   速度 1
(1,2) 时间 1   速度 1/16
(2,2) 时间 17 速度1/4
(3,2) 时间 21 速度1/8
(3,3) 时间 29 速度 1/4

方法:这是最短路径的问题,我们可以计算出所有的时间,在最小的时间单位(即从一次细胞移动到下一个最低高度的时间)。由于在最高高度的运动是慢251倍,有可能是在路径中的200个步骤,我们需要至少59位,所以开longlong/int64.然后就可以了,为了避免掉精度的错误,我们要加个小数输出的优化,优化如下:

double get2(double x)
{
    double q;
    long long w=floor(x*1000);
    if(w%10<5)
    {
        w/=10;
        q=w/100.0;
        return q;
    }
    else if(w%10>5)
    {
        w/=10;q=(w+1)/100.0;
        return q;
    }
    else
    {
        w/=10;
        if((w%10)%2==0)
        {
            q=(w+1)/100.0;
            return q;
        }
        else
        {
            q=w/100.0;
            return q;
        }
    }
}

优化方法:这个数*1000,然后取小数后两位,然后取mod判断。
代码如下:(请不要copy)

#include<cstdio>
#include<cstring>
#include<cmath>
#define F(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
const int maxn=100;
const int w[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int v,m,n;
int map[maxn][maxn];
double s[maxn][maxn],t[maxn][maxn];
bool vis[maxn][maxn];
long long power[55];
struct e{int x,y;}q[maxn*maxn+20];
double get2(double x)
{
    double q;
    long long w=floor(x*1000);
    if(w%10<5)
    {
        w/=10;
        q=w/100.0;
        return q;
    }
    else if(w%10>5)
    {
        w/=10;q=(w+1)/100.0;
        return q;
    }
    else
    {
        w/=10;
        if((w%10)%2==0)
        {
            q=(w+1)/100.0;
            return q;
        }
        else
        {
            q=w/100.0;
            return q;
        }
    }
}
void SPFA()
{
    int head=-1,tail=0,i,tx,ty;
    double tmd;
    q[0].x=0,q[0].y=0;
    memset(vis,false,sizeof(vis));
    vis[0][0]=true;
    while(head!=tail)
    {
        if(++head==maxn*maxn) head=0;
        F(i,0,3)
        {
            tx=q[head].x+w[i][0];
            ty=q[head].y+w[i][1];
            if(tx<0 || tx==m || ty<0 ||ty==n) continue;
            tmd=t[q[head].x][q[head].y]+1.0/s[q[head].x][q[head].y];
            if(tmd<t[tx][ty])
            {
                t[tx][ty]=tmd;
                if(!vis[tx][ty])
                {
                    if(++tail==maxn*maxn) tail=0;
                    q[tail].x=tx;
                    q[tail].y=ty;
                    vis[tx][ty]=true;
                }
            }
        }
        vis[q[head].x][q[head].y]=false;
    }
}
int main()
{
    freopen("cowski.in","r",stdin);
    freopen("cowski.out","w",stdout);
    scanf("%d %d %d",&v,&m,&n);
    power[0]=1;
    F(i,1,50) power[i]=power[i-1]<<1;
    F(i,0,m-1)
      F(j,0,n-1)
      {
        scanf("%d",&map[i][j]);
        t[i][j]=power[31];
      }
    s[0][0]=v;
    F(i,0,m-1)
     F(j,0,n-1)
     {
         if(map[i][j]>map[0][0]) s[i][j]=v/double(power[map[i][j]-map[0][0]]);
         else s[i][j]=v*power[map[0][0]-map[i][j]];
     }
    t[0][0]=0;
    SPFA();
    printf("%.2lf\n",get2(t[m-1][n-1]));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值