首页 > 代码库 > hdu5037 Frog --- 贪心

hdu5037 Frog --- 贪心

有一只萌萌哒小青蛙要过河,过河路线可以看成一个数轴,起点为0,终点为m。

小青蛙不会游泳,只能跳到数轴上一些有树桩的点直到跳过河,小青蛙一次能跳的最大距离是L。

小青蛙想用尽量少的步数过河,而你想让他跳尽量多的次数。

现在你可以向数轴上一些位置添加树桩,使青蛙顺利过河,并达到你的目的。青蛙是以最佳策略过河的。


纠结的题意。。

首先分析一下青蛙的最佳策略,一定是每次跳的越远越好,

假设a<b,那么通过a能到达的点,b一定能到达,所以当有多个点可以选择时,一定跳到最远的那个。

既然青蛙每次尽量跳的远,距离最大为L,那么两个树桩距离<=L的,一定一次就跳过了。

而L+1的距离刚好挑不到,把L+1的距离分为两步来跳,对我们来说是最划算的。

既然如此,我们如何添加树桩呢。

可以发现,如果青蛙可以跳到的范围内本身就有树桩,它一定会跳的最远的那个,此时我们在该点之前之后添加点都没意义(要么没用,要么便宜它了)

如果没有可以跳到的,那么我们就得添加树桩,青蛙必定会跳到这个点,我们的目的是要使它尽量的靠右。

这个点的位置和青蛙现在所在位置以及上一个树桩的位置有关,即 要让青蛙从上次位置刚好跳不到。

所以要记录当前位置p和last,添加树桩的点就是max(p+1,last+l+1)


#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#pragma comment(linker, "/STACK:16777216")
#define eps 1e-6
#define ll long long
using namespace std;
const int maxn=200010;

int r[maxn];

int main()
{
    int i,p,T,ans,n,m,l,cas=1,last;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&l);
        for(i=0;i<n;i++)
            scanf("%d",&r[i]);
        sort(r,r+n);
        r[n]=m;
        ans=0,p=0,last=-l;
        for(i=0;i<=n;i++)
        {
            ans+=(r[i]-p)/(l+1)*2;
            last+=(r[i]-p)/(l+1)*(l+1);
            if(r[i]-last>l)
            {
                last=p+(r[i]-p)/(l+1)*(l+1);
                p=r[i];
                ans++;
            }
            else p=r[i];
        }
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}
/*
999
4 17 3
4 7 12 16
4 18 3
4 7 12 16
4 19 3
4 7 12 16
*/


hdu5037 Frog --- 贪心