HDU 5037 Frog

题意:一只青蛙要过河,河面上现在有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);
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值