题意:
一个青蛙过河,他它跳跃范围是k (k范围内能跳到任何地方),它不能游泳,只能通过河上面的木桩,可以看作是线性的,抵达m起点是0,
你首先一定要让它能过和,然后让他条约次数最大。
题解:
很明显,在他的跳跃范围内,他一定会选择一个最远的点来跳跃。如果这个范围内有石头,你就不应该添加石头,你在改石头之前添加是无用功,
之后添加是对青蛙有利 的,所以,只有在他的跳跃范围之内没有石头的情况时,你才需要添加石头,当然添加石头要尽可能的向左,
但是要保证前一个石头不能一下子跳过来,只能是该点向后跳。
直接模拟一步一步跳超时,,亲测。
然后写了一个二分每次选择能跳的最远的,,,跑到1000ms wa。。。
后来发现,根本不用二分石头,直接一个石头一个石头跳就可以了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=2e5+5;
int n,m,k;
int stone[maxn];
int main(){
int T;
scanf("%d",&T);
for(int ca=1;ca<=T;++ca){
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;++i)
scanf("%d",&stone[i]);
stone[n+1]=m;
sort(stone+1,stone+1+n);
int pos=0,step=0,pre=-k;
for(int i=1;i<=n+1;++i){
step+=(stone[i]-pos)/(k+1)*2;
pre+=(stone[i]-pos)/(k+1)*(k+1);
if(stone[i]-pre>k){
pre=pos+(stone[i]-pos)/(k+1)*(k+1);
step++;
}
pos=stone[i];
}
printf("Case #%d: %d\n",ca,step);
}
return 0;
}