51Nod 1257 - 背包问题 V3(二分)
【题目描述】
【思路】
二分最大化平均值,设被选择的集合是 那么对于某个单位价值 我们去验证物品集合 中的单位价值能否达到 即验证下面的式子是否成立 移项后,等价于验证 是否成立,这样二分 的值,然后每个物品就按照 排序然后贪心选择即可
#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;
}