题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5037
题目的意思比较简单,
说,一个青蛙需要过河,河宽抽象成一维坐标轴,为m。初始,青蛙在0点,每次他最多能条L个单位长度,即从0 ->L,初始时候有n个石头在河内,并且青蛙可以踩在石头上。但是,河内的石头不一定能够使得青蛙跳到对岸。现在上帝可以帮助青蛙,即放入河内一些石头使青蛙能够过河,但是,上帝想要青蛙跳最多的次数。问青蛙最多条几次才能够过河。 N, M, L (0<=N<=2*10^5,1<=M<=10^9, 1<=L<=10^9)。
比赛期间没有想明白为什么。。
看题解后明白了,贪心。。
我们应该明白的知道一些结论:
1.青蛙每次都会以最优的策略来的,所以不可否认的是,如果它每次都条到最远的话,肯定步数会更少。
2.如果最初始的时候,石头就能过跳过,上帝加石头是无用的。。为什么?
因为,如果你加到能够跳到最远的石头的左边,它会忽略,加到右边,它可以选择的策略会更优,这不是上帝想要看到。所以....
所以,我们的贪心策略就出来了。
1.尽可能的把不能跳过的距离分成多的L+1份,这样青蛙需要跳过的步数就会更多。
2.需要注意的是,青蛙的下一步是和它前面的一步长度是有关系的。。
如下图:
Code:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 2 * 1e5 + 4;
int n, m, L, po[N];
int solve()
{
int pre = L, ans = 0;
for(int i = 1; i <= n; i ++){
int x = (po[i] - po[i - 1]) / (L + 1);
int y = (po[i] - po[i - 1]) % (L + 1);
if(y + pre >= L + 1){ //
pre = y;
ans += (x * 2 + 1);
}
else {
pre = y + pre;
ans += x * 2;
}
}
return ans;
}
int main()
{
// freopen("1.txt", "r", stdin);
int T, k = 1;
scanf("%d", &T);
while(T --){
scanf("%d %d %d", &n, &m, &L);
for(int i = 1; i <= n; i ++){
scanf("%d", &po[i]);
}
po[0] = 0; po[++ n] = m;
sort(po, po + n);
printf("Case #%d: %d\n", k ++, solve());
}
return 0;
}