hdu5037 Frog --- 贪心

来源:互联网 发布:linux网络通信 编辑:程序博客网 时间:2024/03/29 22:29

有一只萌萌哒小青蛙要过河,过河路线可以看成一个数轴,起点为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 longusing 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;}/*9994 17 34 7 12 164 18 34 7 12 164 19 34 7 12 16*/


0 0
原创粉丝点击