https://blog.csdn.net/hzoi_ztx/article/details/54898323
http://www.51nod.com/Challenge/Problem.html#!#problemId=1257
给定n个二元组((value_i, cost_i)),(value_i)是选择此二元组获得的价值(非负),(cost_i)是选择此二元组付出的代价(非负),设(x_i (x_i \in{{0,1}} ))代表第i个二元组的选与不选,最大(小)化下式
r
=
∑
v
a
l
u
e
i
⋅
x
i
∑
c
o
s
t
i
⋅
x
i
r = \frac {\sum {value_i · x_i} } {\sum {cost_i · x_i} }
r=∑costi⋅xi∑valuei⋅xi
如何解决这个问题呢?化简可以得到
r
⋅
∑
c
o
s
t
i
⋅
x
i
=
∑
v
a
l
u
e
i
⋅
x
i
r · \sum {cost_i · x_i} = \sum {value_i · x_i}
r⋅∑costi⋅xi=∑valuei⋅xi
二分r,选前k个求(value_i – r · cost_i)的和,大于eps说明r还能再大。
struct e{
int v, c;
double r;
}a[maxn];
bool cmp(e a, e b){return a.r > b.r;}
int main()
{
int n, k;
n = in(); k = in();
for (int i = 0; i < n; ++i){
a[i].c = in(); a[i].v = in();
}
double l = 0, r = 50001, ans;
for (int i = 0; i < 32; ++i){
double m = (l + r) / 2;
for (int j = 0; j < n; ++j) a[j].r = a[j].v - m * a[j].c;
sort(a, a + n, cmp);
double sum = 0;
for (int j = 0; j < k; ++j) sum += a[j].r;
if (sum <= eps){
ans = l;
r = m;
}else{
l = m;
}
}
for (int i = 0; i < n; ++i) a[i].r = a[i].v - ans * a[i].c;
sort(a, a + n, cmp);
ll sa = 0, sb = 0;
for (int i = 0; i < k; ++i){
sa += a[i].v, sb += a[i].c;
}
ll c = gcd(sa, sb);
sa /= c, sb /= c;
out(sa); putchar('/'); out(sb);
return 0;
}