hdu5037Frog 贪心

//一只青蛙从0跳到m
//每次只能跳(0~L)的长度,它只能在石头上停留
//在[0,m]之间有n个石头 , 
//问在哪些地方添加石头能使得其青蛙能从0跳到m且
//跳的步数最大 , 青蛙采用最优策略
//n<=2e5 , m ,l<= 1e9
//贪心策略:对于青蛙到了位置now其下一个石头如果能
//跳到 , 那么跳到能到达的最远的石头
//如果不能跳到 , 那么在其pre+l+1添加一块石头
//由于m<=1e9 , 直接处理会超时,所以对于两个隔得很远的两块
//石头 , 在(l+1)中间最多跳两次 , 所以直接将其除(l+1)
//然后处理
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
const int maxn = 2e5+10 ;
const int inf = 0x7fffffff ;
int a[maxn] ;
int main()
{
   // freopen("in.txt" , "r" , stdin) ;
    int t ;
    scanf("%d" , &t) ;
    int cas = 0 ;
    while(t--)
    {
        int n ;int m , l ;
        scanf("%d%d%d" , &n , &m , &l) ;
        for(int i = 1;i <= n;i++)
        scanf("%d" , &a[i]) ;
        sort(a+1 , a+1+n) ;
        while(a[n] > m)
        n-- ;
        a[++n] = m ;
        int pre = -1 ;
        int now = 0 ;
        int ans = 0 ;
        int i = 1 ;
        while(i <= n)
        {
            if(now + l < a[i])
            {
                int tmp = (a[i] - now)/(l+1) ;
                if(tmp > 1)
                {
                    ans += (tmp - 1)*2 ;
                    if(pre == -1)
                    pre = 1 + (tmp-2)*(l+1) ;
                    else pre += (tmp-1)*(l+1) ;
                    now += (tmp-1)*(l+1) ;
                }
                else
                {
                    int temp = now ;
                    if(pre == -1)now = 1 ;
                    else now = pre + l + 1 ;
                    pre = temp ;
                    ans++ ;
                }
            }
            else
            {
                if(i < n && now + l >= a[i+1])
                {
                    i++ ;
                    continue ;
                }
                pre = now ;
                now = a[i];
                ans++ ;
                i++ ;
            }
        }
        printf("Case #%d: " , ++cas) ;
        printf("%d\n" , ans) ;
    }
    return 0 ;
}

















你可能感兴趣的:(hdu5037Frog 贪心)