HDOJ 5037 Frog

66 篇文章 0 订阅
11 篇文章 0 订阅

题意:青蛙从0到m,每次跳的距离不大于L,可以在任意位置添加任意数量的石头,青蛙会自动选择跳跃次数最少的方案,求青蛙可能的最大的跳跃次数。

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5037

思路:模拟+贪心。将每次青蛙跳跃的过程模拟,在跳跃过程中贪心选择出相同跳跃次数情况下距离最短的情况。若该处没有石子就加石子。

注意点:直接模拟可能因为跳跃次数过多而TLE,因此当两块石头过远的时候,可以一次处理完这两块石头间的所有过程。跳跃次数为 len/(L+1)。

AC代码如下:

Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor
117026342014-09-22 18:30:53Accepted5037812MS1080K2131 BG++luminous11

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int ncase;
int len[200005];
int m, n, l;
int dis = 0;
int cnt = 0;
int k = 1;
int tmp = 0;

void init ()
{
    cnt = 0;
    k = 1;
    dis = 0;
    tmp = -10000000;
    memset ( len, 0, sizeof ( len ) );
    len[0] = 0;
}

int solve( )
{
    int ans = 0;
    int i = 0;
    while ( dis < m )
    {
        //cout << "dis = " << dis << endl;
        while ( len[i] <= l + dis && i <= n )
        {
            i ++;
        }
        if ( i > n )
        {
            return ans + 1;
        }
        if ( len[i - 1] > dis )
        {
            tmp = dis;
            dis = len[i - 1];
            ans ++;
        }
        else
        {
            k = ( len[i] - dis ) / ( l + 1 ) - 1;
            if ( k > 0 )
            {
                tmp = max( dis + 1, tmp + l + 1 ) + ( k - 1 ) * ( l + 1 );
                dis += k * ( l + 1 );
                ans += k * 2;
            }
            else
            {
                k = dis;
                dis = max ( dis + 1, tmp + l + 1 );
                tmp = k;
                ans ++;
            }
        }
        //cout << ans << endl;
    }
    return ans;
}

int main()
{
    //ios::sync_with_stdio( false );
    scanf ( "%d", &ncase );
    for ( int t = 1; t <= ncase; t ++ )
    {
        init();
        scanf( "%d%d%d", &n, &m, &l );
        for ( int i = 1; i <= n; i ++ )
        {
            scanf ( "%d", &len[i] );
        }
        len[++n] = m;
        sort( len + 1, len + n );
       /* for ( int i = 0; i <= n; i ++ )
        {
            cout << len[i] << ' ';
        }
        cout << endl;*/
        cnt = solve ( );
        printf( "Case #%d: %d\n", t, cnt );
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值