51Nod 1257 - 背包问题 V3(二分)

【题目描述】
在这里插入图片描述
【思路】
二分最大化平均值,设被选择的集合是 SS 那么对于某个单位价值 xx 我们去验证物品集合 SS 中的单位价值能否达到 xx 即验证下面的式子是否成立 iSpiwi>=x\sum_{i \in S} \frac{p_i}{w_i}>=x 移项后,等价于验证 iS(pixwi)>=0\sum_{i \in S}(p_i-xw_i)>=0 是否成立,这样二分 xx 的值,然后每个物品就按照 pixwip_i-xw_i 排序然后贪心选择即可

#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;
}
posted @ 2018-11-05 17:20  不想吃WA的咸鱼  阅读(146)  评论(0编辑  收藏  举报