版权声明:希望能帮到弱校的ACMer成长,因为自己是弱校菜鸡~~~~ https://blog.csdn.net/Mr__Charles/article/details/82875808
题目原文
有n个物品的重量和价值分别是w[i]和v[i]。从中选出k个物品使得单位重量的价值最大。数据范围
1<=k<=n<=10^4
1<=w[i],v[i]<=10^6
解题思路
定义C(x):可以选择使得单位重量的价值不小于x。
原问题就变成了求满足C(x)的最大的x。
假设我们选择的物品的集合是S,那么它们单位重量的价值是
∑v[i]/∑w[i]
∑v[i]/∑v[i]>=x变形得∑(v[i]-x*w[i])>=0.
因此可以对v[i]x*w[i]的值进行排序贪心的进行选取
因此就变成了C(x)=((v[i]-x*w[i])从大到小排列中前k个的和不小于0)。
每次判断的时间复杂度为O(nlogn)。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e4;
const int INF = 0x3f3f3f3f;
int n,k;
double m[MAXN+5];
struct goods{
int w,v;
}g[MAXN+5];
bool cmp(double a,double b){
return a > b;
}
bool judge(double x){
for(int i = 0; i < n; ++i)
m[i] = g[i].v - g[i].w * x;
sort(m,m+n,cmp);
double sum = 0;
for(int i = 0; i < k; ++i)
sum += m[i];
return sum >= 0;
}
void solve(){
double L = 0,R = INF;
for(int i = 0; i < 100;++i){
double mid = (L + R)/2;
if(judge(mid)) L = mid;
else R = mid;
}
printf("%.2lf\n",R);
}
int main(){
while(~scanf("%d%d",&n,&k)){
for(int i = 0; i < n; ++i)
scanf("%d%d",&g[i].w,&g[i].v);
solve();
}
return 0;
}