1. 程式人生 > >Ice Cream Tower Gym - 101194D (貪心 + 二分 )

Ice Cream Tower Gym - 101194D (貪心 + 二分 )

題目連結 : https://cn.vjudge.net/problem/Gym-101194D 

題目大意 : 給你n個冰激凌球,讓你用這些冰激凌球去壘冰激凌,要求是下面的這一個必須是他上面一個的兩倍大,一個冰激凌需要m個冰激凌,問你最多能造幾個冰激凌.

具體思路:  貪心 + 二分 ,首先對輸入的n個冰激凌球進行排序,從小到大開始,然後對答案進行二分,從當前的開始,找第一個滿足的,然後找完一個再繼續找下一個,如果當前要檢測的答案是k,那麼就需要找k層滿足情況的.

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 500000+10;
ll a[maxn],b[maxn];
ll n,m;
ll Max(ll t1,ll t2)
{
    if(t1<t2)return t2;
    return t1;
}
bool judge(ll t)
{
    ll ans=0;
    for(int i=1; i<=t; i++)
    {
        b[i]=a[i];
    }
    int x=1;
    if(x==m)return true;
    int f=t;
    while(1)
    {
        for(int i=1; i<=t; i++)
        {
            if(f>=n)return false;
            f++;
            while(1)
            {
                if(a[f]>=b[i]*2)
                {
                    b[i]=a[f];
                    break;
                }
                if(f+1>n)return false;
                f++;
            }
        }
        x++;
        if(x==m)return true;
    }
}
int main()
{
    ll T;
    scanf("%lld",&T);
    int Case=0;
    while(T--)
    {
        scanf("%lld %lld",&n,&m);
        for(ll i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
        }
        sort(a+1,a+n+1);
        ll l=0,r=n/m;
        ll ans=0;
        while(l <= r )
        {
            int mid = ( l + r ) / 2;
            if(judge(mid))
            {
                ans=Max( ans, mid );
                l = mid + 1 ;
            }
            else  r = mid - 1 ;
        }
        printf("Case #%d: ",++Case);
        printf("%lld\n",ans);
    }
    return 0;
}