题意:
一只足够聪明的青蛙要过河 它每次最多跳L米 河宽m米 河中有n个石头 你可以任意的添加石头 问 青蛙最多跳几次
思路:
明显的考验想法 题的方向不是乱搞题就是贪心题
首先我们明确 想要次数最多一定要每次跳的最短 但是不能忽略青蛙足够聪明 因此想到可以每2步跳L+1米
考虑到河中本来就有一些石头 所以每次跳之前要先判断是不是能跳到石头上 如果能就不需要加石头 因为加石头近了青蛙不理你 加远了青蛙跳得远就不符合次数最多
最后就是本题最难想的点 每一步的长度受上一步的长度限制 那么就需要记一个last 同时每次少跳一个L+1 用来满足last的限制 保证后面仍然可以使用L+1这种跳法的策略
注意:
石头要排序 输入不是有序的
如果用i表示当前位置前面的石头的序号 那么每次跳之后都要维护i 要不然可能会踩在i石头上
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<cassert>
#include<vector>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define N 200010
int x[N];
int T, t, n, m, L, ans;
int main() {
int i, now, last, time;
scanf("%d", &T);
for (t = 1; t <= T; t++) {
scanf("%d%d%d", &n, &m, &L);
for (i = 1; i <= n; i++)
scanf("%d", &x[i]);
n++;
sort(x + 1, x + n);
x[n] = m;
now = ans = 0;
last = L + 1;
for (i = 1; now < m;) {
if (now + L >= x[i]) {
ans++;
for (; i <= n; i++) {
if (now + L < x[i])
break;
}
i--;
last = x[i] - now;
now = x[i];
i++;
} else {
time = (x[i] - now) / (L + 1) - 1;
ans += time * 2;
now += time * (L + 1);
ans++;
last = L + 1 - last;
now += last;
for (; i <= n; i++) {
if (x[i] > now)
break;
}
}
}
printf("Case #%d: %d\n", t, ans);
}
return 0;
}