这题我都不想吐槽了,北京区域赛的资格没拿到就怪我这题的bug一直没找出来
看网上别人都是用贪心做的,我觉得我是分情况讨论的。
题意:
青蛙在x轴坐标上跳,青蛙初始坐标为0,终点为M,每次青蛙最远跳l个单位且青蛙必须跳到有石头的坐标。 已存在N个石头,石头坐标为a1,a2,..an, 现在你可以放任意多个石头在任意坐标上, 青蛙会尽快跳到终点,求青蛙跳到终点最多需要多少步
首先,因为我们要使得青蛙跳的步数尽可能多,所以我们会尽量使得青蛙每两步跳的距离为l+1。(这个模拟一下就可以得到), 但青蛙想尽可能跳少一点,所以青蛙每次都会
跳到能跳的最远距离。 所以我们需记录青蛙上一步跳的距离才能算出这步的最优距离
例如:
青蛙从0跳到8,每次最远跳4,第一步青蛙跳1, 第二步跳到5,第三步跳到8
因为青蛙每两步跳l+1 最优 , 所以我们可以对区间[L,R] 先预处理出 ans+= 2*(R-L)/(L+1) ,然后对(R-L)%(L+1)讨论
设第一个石头坐标为0,
例如
设记录值为t
1 8 4
1
青蛙先跳一步到坐标1, 记录上一步的距离为1,然后对【1,8】区间计算时,青蛙会用两步来跳l+1距离得 ans+= 2, 青蛙到达6, 剩下的距离即余数yu = (8-1)%5= 2
因为记录的值为1,所以青蛙第三步是从5跳到6,但是青蛙,从5已经可以跳到8了, 所以这是对剩下的距离不处理,且更新记录值为3 即情况 t+yu<= l
1 10 4
2
同上可算得对【1,10】区间计算时记录值为2,yu= (9-2)%5= 2,因为记录的值是2,所以青蛙第三步是从5跳到7,但是青蛙从5不能跳到10,所以青蛙必须跳到7之后才能跳过或跳到该石头 即情况t+yu> l
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;
#define maxn 222222
int a[maxn];
int main()
{
int T;
scanf("%d",&T);
for(int C= 1; C<= T; C++)
{
int n, m ,l;
scanf("%d %d %d",&n,&m,&l);
for(int i= 1; i<= n; i++)
scanf("%d",&a[i]);
sort(a+1, a+n+1);
a[0]= 0;
a[n+1]= m;
a[n+2]= INT_MAX;
int ans= 0, L= 0, R= a[1], time= l, i= 0;
while(i<= n)
{
if(L> a[n])
break;
int xx= (R- L)/(l+1);
ans+= xx*2;
int yu= (R- L)%(l+1);
int LL;
if(yu + time> l)
ans++, LL= L+ (l+1)*xx;
else if(yu+ time <= l)
LL= L + (l+1)*xx- time;
for(int j= i; j<= n+2; j++)
if(a[j]- LL<= l)
{
L= a[j];
R= a[j+1];
time= a[j]- LL;
i= j;
} //看那个石头是青蛙跳不过去的,跳的过去的石头都不考虑
else
break; // 这里忘记break TLE了十多次
}
printf("Case #%d: %d\n",C,ans);
}
return 0;
}