hdu 5037 Frog(贪心)

题意:有一只青蛙想从0点跳到M点、从0点到M点有N块石头,给出你N块石头的位置、青蛙跳跃的长度为0~L、你上帝,当青蛙无法跳跃的时候你可以帮助它、

可以无限制的在池塘内任何一点添加石头,并且你是仁慈的,一定会让这个青蛙到达对岸 也就是M点、 你想让青蛙尽可能的跳跃多次,到达对岸、青蛙是聪明的,

它跳跃的时候会选取它跳跃的最优解来跳跃、 问这只青蛙一最多跳跃多少次可以到达M点、


自己做的时候也是很朦胧,想的头大、 看了别人的解题报告,最后终于搞懂了该怎么做、


思路:一道贪心题、  首先定义三个整形变量k,x,y、 三个变量k代表的是青蛙的位置到现在我要找的位置之前的位置的距离 (比如说,有三块石头,分别在坐标轴上的3  7  15  三个点,青蛙跳跃的最大距离L=14 , 此时青蛙的位置在三的位置上、  当找到7的位置时,k=3-7=4  此时的距离小于14 所以我不一定要跳跃,我需要往后面找,当我找到15这个点的时候 k=4+(15-7)  因为从3到7的距离我已经计算过了,此时我需要找的位置为7到15这个点,此时k=12  由于L=14 所以我也不一定要跳跃,k的值表示的就是 青蛙的位置与要找的位置之间的距离)    x变量表示的是两个石头之间的相对距离, 相对距离指的是两个石头之间的距离有可能大于青蛙跳跃的距离L,所以一定要青蛙跳跃两次,因为两个石头之间的距离如果大于L青蛙便跳不过去,这样便有机会使它跳跃的次数变得更多、所以x应该等于两个石头之间的距离%L+1取余, 如果两个石头之间的距离为L那么便符合青蛙跳跃最大的条件了,但是呢,我想要使青蛙跳跃的次数最多,所以我不想让它跳过去,不想让它跳过去的最短距离便为L+1、 这样便可以使青蛙跳跃的次数最大、    y代表的是两个石头中间的距离中有几个L+1 、 如果有一个L+1那么我跳跃的次数一定是两次、 这个是一定的  、 其实x和y都是很好理解的,最主要的是k 与x之间的关系, 


k与x之间的关系,k与x之间有两种情况,一种是k+x<=L 那么我有可能跳跃,因为x的值是相对的x,所以其中有可能有L+1段是超过的,这个看代码应该就可以读懂、如果k+x<+L 就说明我不需要跳跃,因为此时不一定是最优解、 而另一种情况k+x> L 此时我需要跳跃,跳跃的次数为多少呢? 一定为y*2+1次 因为我x中间有可能有超过L+1的部分所以要y*2 那么此时我的相对x值与k值相加是>L的所以需要多加一个1   那么此时我的k值为多少呢? k应该等于x 因为我想要k值应该取最大,k值越大那么我越有可能大于L 那么青蛙跳跃的次数就越多、  最后输出青蛙跳跃的次数就可以了、  


k的值要赋值为L ,因为默认第一次一定是能跳跃的,跳跃的次数为y*2+1、 这个自己想一想就可以理解的、


AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200005;
int N,M,L,T;
int w[maxn];
int ans,x,y,k,cnt;

int main()
{
    scanf("%d",&T);
    cnt=0;
    while(T--){
        scanf("%d %d %d",&N,&M,&L);
        for(int i=1;i<=N;i++)
            scanf("%d",&w[i]);
        w[++N]=M; ans=0;w[0]=0;
        sort(w,w+N);
        k=L;
        for(int i=1;i<=N;i++){
            x=(w[i]-w[i-1])%(L+1);
            y=(w[i]-w[i-1])/(L+1);
            if(x+k<=L){
                k+=x;
                ans+=y*2;
            }
            else{
                k=x;
                ans+=y*2+1;
            }
        }
        printf("Case #%d: %d\n",++cnt,ans);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值