1. 程式人生 > >Gym - 101670B(Pond Cascade )二分或貪心

Gym - 101670B(Pond Cascade )二分或貪心

題意:

給定n個池塘,往裡面注水,給定單位時間的注水量。

注:1、這n個池塘是同時注水的,也就是說任一時間內,每個池塘注入的水量是相同的。

2、這n個池塘所在高度是逐漸遞減的,如果第i個池塘滿了後繼續注水,水將會往第i+1個池塘流,依次類推。

求①最後一個池塘剛好滿的時間;②所有池塘剛好滿的時間。

題解:

一、二分時間,檢驗答案

二、直接貪心

一、二分時間,檢驗答案(詳解見程式碼)

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const double INF=1e9+10;
ll a[maxn];
ll n,f;
bool judge1(double t)
{
    double sum=0;//記錄所有池塘的溢位量
    for(int i=0;i<n-1;i++)
    {
        sum+=t*f;//每次往裡面注入 t*f 單位的水
        if(sum<a[i])//和第i池塘的容量作比較
            sum=0;//如果小於a[i] 則sum裡的水全部進入第i個池塘裡面
        else
            sum-=a[i];//否則sum裡的水變為 sum-a[i]
    }
    sum+=t*f;
    if(sum>=a[n-1])//迴圈結束後 如果sum裡的水大於等於最後一個的容量,則說明t時間內最後一個池塘會注滿
        return true;
    else
        return false;
}
bool judge2(double t)
{
    double sum=0;//記錄所有池塘的溢位量
    for(int i=0;i<n;i++)
    {
        sum+=t*f;//每次往裡面注入 t*f 單位的水
        if(sum<a[i])//和第i池塘的容量作比較,如果sum裡的水小於第i個池塘的容量,則說明有池塘不滿,直接返回false
            return false;
        sum-=a[i];//否則sum裡的水變為 sum-a[i]
    }
    return true;
}
int main()
{
    int K=100;//(100次二分,精確答案)
    while(scanf("%lld%lld",&n,&f)!=EOF)
    {
        ll MAX=0;
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
        }
// 1.
        double l=0,r=INF;
        double t1,t2;
        K=100;
        while(K--)
        {
            double mid=(l+r)/2;
            if(judge1(mid))
            {
                r=mid;
            }
            else
            {
                l=mid;
            }
        } t1=r;
// 2.
        K=100;
        l=0,r=INF;
        while(K--)
        {
            double mid=(l+r)/2;
            if(judge2(mid))
            {
                r=mid;
            }
            else
            {
                l=mid;
            }
        } t2=r;
        printf("%.6lf %.6lf\n",t1,t2);
    }
    return 0;
}

二、直接貪心

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const double INF=1e9+10;
ll a[maxn];
int main()
{
    ll n,f;
    while(scanf("%lld%lld",&n,&f)!=EOF)
    {
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
        }
// 1.
        double su1=0,sum1=0,t1=INF;
        for(int i=n-1;i>=0;i--) //從最後一個池塘開始
        {
            sum1+=a[i];
            su1+=f;
            t1=min(t1,sum1*1.0/su1);//求最後m個所有時間的平均值
        }
// 2.
        double su2=0,sum2=0,t2=0;
        for(int i=0;i<n;i++)
        {
            sum2+=a[i];
            su2+=f;
            t2=max(t2,sum2*1.0/su2);
        }
        printf("%.6lf %.6lf\n",t1,t2);
    }
    return 0;
}