二分,字面上的意思,将一个问题分为两个变简的子问题,从而使问题变得简化
引入:最大化平均值
有n个物品的重量和价值分别是wi和vi。从中选出k个物品使得单位重量的价值最大。。。
向这些题,通常可以使用二分搜索法就可以解决了。
设:C(x) = 可以选择使得单位重量的价值不小于x
那么问题可以变成求满足C(x)的最大x
这样的话,我们就要去找 x 的范围
若输入为n = 3 k = 2 (w, v) = {(2, 2),(5, 3),(2, 1)}
(2, 2) 单位重量的价值为2/2=1;
(5, 3) 单位重量的价值为3/5=0.6;
(2, 1) 单位重量的价值为1/2=0.5;
最后我们就知道了x的范围0.5~1
好了,看看部分代码:
二分部分
double l = 0.5, r = 1;
for(int i = 0; i < 100; i++)
{
double mid = (l + r)/2;
if(judje(mid)) l = mid;
else r = mid;
}
我们用循环次数作为终止条件,可以这么想一次二分将范围缩小一半,100次之后精度范围就变成了10^(-31),这样子就不用担心的答案有误了。
double judje(double x)
{
for(int i = 0; i < n; i++)
{
y[i] = v[i] - x*w[i];
}
sort(y, y+n);
double sum = 0;
for(int i = 0; i < k; i++)
{
sum += y[n-i-1];
}
return sum >= 0;
}
v[i] - x*w[i]是在假设平均重量价值为x时,此物品所多余的价值。
然后就排序贪心一下就好了^^
此方法的题:POJ(1064)POJ(2456)
若有错,请指导