有一只萌萌哒小青蛙要过河,过河路线可以看成一个数轴,起点为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
*/