1. 程式人生 > 實用技巧 >洛谷P4653 [CEOI2017]Sure Bet

洛谷P4653 [CEOI2017]Sure Bet

題目

https://www.luogu.com.cn/problem/P4653

思路

最大化可能的最小收益,最大值最小,想必大家已經熟悉二分題的這個套路了。列舉一個值x,模擬,檢驗是否能選A和選B的收益都達到x。

顯然要先選權值大的燈,所以我們降序排序。

關於這個檢驗,我用的是最暴力的方法,若A不行,就加到它行;再看B,也是如此。注意因為選取燈泡有花費,成本變高,這時A又不一定可行了,之後我們反覆橫跳,直到AB都滿足條件。

若可以出現AB都滿足的情況,則該x值可行。

程式碼

#include<cstdlib>
#include<algorithm>
#define inf 0x3f3f3f3f
#define eps 1e-6
#define maxn (int)(1e6+10)
#define db double
using namespace std;
int n;
db a[maxn],b[maxn];
int ok(db x){
    int i=0,j=0;
    db suma=0,sumb=0;
    while(suma-i-j<x||sumb-i-j<x){
        while(suma-i-j<x){
            if(i>n) return 0;
            suma+=a[++i];
        }
        while(sumb-i-j<x){
            if(j>n) return 0;
            sumb+=b[++j];
        }
    }
    return 1;
}
bool cmp(db x,db y){
    return x>y;
}
int main(){
    int i,j;
    db l,r,mid;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%lf%lf",&a[i],&b[i]);
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+n+1,cmp);
    l=0;r=inf;
    while(r-l>eps){
        mid=(l+r)/2.0;
        if(ok(mid)) l=mid;
        else r=mid;
    }
    printf("%.4lf",l);
    // system("pause");
    return 0;
}