题意:
在一片河塘中,有只青蛙从0点开始,要跳到m点,这条线上起初有n个荷叶,每次青蛙最大能跳k米
现在让你添加一些荷叶,让他能跳到m点,问最大的跳跃次数,注意,青蛙每次采取最优策略(尽量少跳)
思路:
青蛙采取最优策略的话就是每次选能跳到的最远点跳,队友存在的荷叶,我们没办法做手脚
只有在青蛙没法往前跳,需要我们添加荷叶的时候,我们贪心的选择一些位置,让他多跳一些
假如青蛙跳到的上一个位置是pre(坐标),并且无法跳到下一个位置a[i],(即:a[i]-pre > k);因为我们要让他多跳,所以我们选尽量小的位置让他跳,但是这个位置必须是他上上个跳到的位置last到达不了的,那就是last+k+1这个位置;
我们令t=pre-last, d=(k+1)-t; 那么pre到a[i] 之间的位置差值是 d-t-d-t-d-t··· 这样的循环,我们只要看他们之间有多少个这样的循环节,还有一个问题就是最后的a[i] 有可能由前面的就可以跳到了,那样就相当于少了一个t的一段,特判一下
需要注意的是,开始时候的last怎么赋值,我因为这个查了好久的bug,,,如果青蛙从初始位置没办法往后跳的话,那我们放的第一个荷叶一定是在第一个位置的,因为前面不会影响,所以last我们要设初值为(-k);
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int a[maxn];
int main() {
int T; scanf("%d", &T);
int kase = 1;
int n, m, k;
while(T--) {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
sort(a+1,a+1+n); a[n+1] = m; a[n+2] = 2e9+77;
int last = -k, pre = 0, ans = 0;
for(int i = 1; i <= n+1; ++i) {
if(a[i] - pre > k) {
int L = a[i] - pre;
int t = pre-last, d = k+1-t;
int t1 = L%(k+1);
ans += (L/(k+1) * 2);
if(t1+t <= k) {
ans--;
pre = a[i]-t1-t;
last = pre-d;
}
else {
pre = a[i]-t1;
last = pre-t;
}
i--;
}
else if(a[i]-pre <= k && a[i+1]-pre > k) {
last = pre;
pre = a[i];
ans++;
}
}
printf("Case #%d: %d\n", kase++, ans);
}
return 0;
}