揹包問題 V3(二分)
阿新 • • 發佈:2018-12-19
【題目描述】 【思路】 二分最大化平均值,設被選擇的集合是 那麼對於某個單位價值 我們去驗證物品集合 中的單位價值能否達到 即驗證下面的式子是否成立 移項後,等價於驗證 是否成立,這樣二分 的值,然後每個物品就按照 排序然後貪心選擇即可
#include<bits/stdc++.h> #define max(a,b)(a>b?a:b) using namespace std; const int maxn=50005; typedef long long ll; ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); } int n,k; ll up,down; struct node{ int p,w; double x; bool operator<(const node& e)const{ return (p-x*w)>(e.p-e.x*e.w); } }a[maxn]; bool check(double x){ for(int i=0;i<n;++i) a[i].x=x; sort(a,a+n); ll sump=0,sumw=0; for(int i=0;i<k;++i){ sump+=a[i].p; sumw+=a[i].w; } if(double(sump)/sumw>=x){ up=sump/gcd(sump,sumw); down=sumw/gcd(sump,sumw); return true; } return false; } int main(){ scanf("%d%d",&n,&k); double le=0,ri=0; for(int i=0;i<n;++i){ scanf("%d%d",&a[i].w,&a[i].p); ri=max(ri,double(a[i].p)/a[i].w); } int cnt=100; while(cnt--){ double mid=(le+ri)/2; if(check(mid)) le=mid; else ri=mid; } printf("%lld/%lld\n",up,down); return 0; }