题意:一只青蛙要过河,河面上现在有n块石头,青蛙每次最长跳L,河宽m。你可以随意在河里加石头,让青蛙跳过
河的步数最多。
题解:1.贪心,可以证明总是使青蛙跳的更近最优;
2.当青蛙可以跳过去的时候,加石子不会更优(只会给青蛙更多种选择)
3.对于x1,x2两个石子间距大于l的情况,使得l + 1分两步跳最优;
4.对于l + 1的分配,取决于青蛙所在石子x0与x1的间距
5.如果青蛙正好在x1上,则把l + 1分成[0,1] 和(1,l + 1]两部分
6.如果x0 != x1 则,把l + 1分成 [0,x1 - x0] 和 (x1 - x0,l + 1]两部分
7.对于x1 到 x2 分配给m个l + 1剩余的距离也需要(在保证青蛙每一步跳的尽可能近的条件下)分情况枚举
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 200005
int rock[MAXN],n,m,l;
int solve()
{
int cur = 0,ans = 0,step = 0;
for(int i = 1;i < n && rock[i] <= m && cur != m;i++)
{
int len = rock[i] - rock[i - 1];
if(len + step <= l)
step += len;
else if(len <= l)
{
cur += step;
step = len;
ans++;
}
else if(step == 0)
{
ans += len / (l + 1) * 2;
step = len % (l + 1);
cur += len - step;
}
else
{
int x = (step + len) % (l + 1);
int x2 = l + 1 - step;
ans += (len + step) / (l + 1) * 2;
if(x + x2 < l)
{
step = x + x2;
ans--;
}
else if(x2 + x == l)
step = 0;
else if(x + x2 > l)
step = x;
cur = rock[i] - step;
}
if(step == l)
{
ans++;
cur += step;
step = 0;
}
}
return ans + (bool)(m - cur);
}
int main()
{
int _,ans;
scanf("%d",&_);
for(int kcas = 1;kcas <= _;kcas++)
{
scanf("%d%d%d",&n,&m,&l);
for(int i = 0;i < n;i++)
scanf("%d",&rock[i]);
rock[n + 1] = 0 , rock[n] = m;
sort(rock,rock + n + 2);
n = unique(rock,rock + n + 2) - rock;
ans = solve();
printf("Case #%d: %d\n",kcas,ans);
}
}