有一只萌萌哒小青蛙要过河,过河路线可以看成一个数轴,起点为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 */
时间: 2024-10-12 06:33:40