网络赛结束,看了大神的代码以后才写出来的,这是一道贪心算法,选局部最优方案:就是相邻两个点不能直接到达做特别讨论。易证:如果两个点不能直接到达,那么每次让青蛙走两步到达(l+1)的距离是最优选择,如果现在青蛙的位置是now ,那么到达now 的那一步走了step,然后对now 后面的那个点进行讨论:如果length=stone[now+1]-stone[now],now+length<=l说明前一步可以到达now+1;这个时候更新now 的位置,试青蛙每一次都能够尽量地跳得远。这样还要把第一次的几种情况讨论一下才能ac,至于复杂度,也只有o(2*10^5),只需要更新now的位置,所以只要遍历一边所有石头的位置就好了
详细看下面ac代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int n,m,l;
int stone[200010];
int cnt;
void solve()
{
sort(stone,stone+n+1);
int step = 0;
int now=0;
int length;
while(now!=n+1)
{
length=stone[now+1]-stone[now];
if((step+length)<=l)
{
if(now==0)
{
cnt++;
}
step+=length;
now+=1;
}
else if(length<=l)
{
step=length;
now+=1;
cnt++;
}
else if(length>l)
{
int a=length/(l+1);
int b=length%(l+1);
if(now==0)
{
now++;
if(b==0)
{
cnt+=2*a;
step=l;
}
else
{
step=b;
cnt+=2*a+1;
}
}
else
{
if(step+b<=l)
{
now++;
cnt+=2*a;
step=step+b;
}
else
{
now++;
cnt+=2*a+1;
step=b;
}
}
}
}
printf("%d
",cnt);
}
int main()
{
int t;
scanf("%d",&t);
for(int k=1;k<=t;k++)
{
cnt=0;
scanf("%d%d%d",&n,&m,&l);
stone[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&stone[i]);
}
stone[n+1]=m;
printf("Case #%d: ",k);
solve();
}
return 0;
}