首页 > 代码库 > 最大化平均值
最大化平均值
n个物品的重量和价值分别是wi和vi。从中选取k个物品使单位重量的价值最大
输入
n = 3
k = 2
(w, v) = { (2, 2), (5, 3), (2, 1) }
输出
0.75(选择0和2号物品,平均价值是(2+1)/(2+2) = 0.75)
一般最先想到的方法可能是把物品按照单位价值排序,从大到小贪心的选取。但是这个方法对于样例得到结果是5/7 = 0.714。
实际上,对于这个问题使用二分搜索法可以很好的解决。我们定义
条件C(x):=可以选择使单位重量的价值不小于x
因此原问题就变成求满足C(x)的最大x。假设我们选了某个物品的集合S,那么它们的单位重量价值为
∑vi / ∑wi
因此变成判断是否存在S满足下面的条件
∑vi / ∑wi >= x,即 ∑(vi - x * wi) >= 0
因此,可以对(vi - x * wi)进行排序贪心地选取
C(x) = ((vi - x * wi)从大到小排列中的前k个的和不小于0)
每次判断的复杂度为O(nlogn)。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 6 #define INF 1000 7 #define MAX_N 1000 8 9 int n, k;10 int w[MAX_N], v[MAX_N];11 double y[MAX_N];12 13 //判断是否满足条件14 bool C(double x)15 {16 for (int i = 0; i < n; i++)17 {18 y[i] = v[i] - x * w[i];19 }20 sort(y, y+n);21 22 //计算y数组中从大到小前k个数的和23 double sum = 0;24 for (int i = 0; i < k; i++)25 {26 sum += y[n-i-1];27 }28 return sum >= 0;29 }30 31 void solve()32 {33 double lb = 0, ub = INF;34 for (int i = 0; i < 100; i++)35 {36 double mid = (lb + ub) / 2;37 if (C(mid)) lb = mid;38 else ub = mid;39 }40 printf("%.2f\n", ub);41 }42 43 44 int main()45 {46 cin >> n >> k;47 for (int i = 0; i < n; i++)48 {49 cin >> w[i] >> v[i];50 }51 solve();52 return 0;53 }
最大化平均值
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。