这题我都不想吐槽了,北京区域赛的资格没拿到就怪我这题的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; }