poj2976(0-1 分数规划)
题意
给定n个二元组 ( a i , b i ) (a_{i},b_{i}) (ai,bi)除去n个,剩下的n-k组成集合S作 ∑ i ∈ S a i ∑ i ∈ S b i \frac{\sum_{i\in S}a_{i}}{\sum_{i\in S}b_{i}} ∑i∈Sbi∑i∈Sai使其达到最大,原题还让将其取到最近整数!
0-1分数规划
这道题是一道很典型的0-1分数规划,网上的资源看了许多,但是好像没有人介绍在求解答案的时候二分的依据,也没有人解释为何要求解max(F(L)),在这里,我将给出解释。
首先还是对整个算法大概做个描述,具体细节一会解释
1.记
F
(
L
)
=
∑
i
=
1
i
=
n
(
a
i
−
L
b
i
)
x
i
F(L)=\sum_{i=1}^{i=n}(a_{i}-Lb_{i})x_{i}
F(L)=∑i=1i=n(ai−Lbi)xi其中
∑
i
=
1
i
=
n
x
i
=
n
−
k
\sum_{i=1}^{i=n}x_{i}=n-k
∑i=1i=nxi=n−k
2.由上面的表达式可以知道对于固定的L使得F(L)最大时即
m
a
x
(
F
(
L
)
)
max(F(L))
max(F(L))为将
a
i
−
L
b
i
a_{i}-Lb_{i}
ai−Lbi进行排序取前n-k大的元素,使其
x
i
=
1
x_{i}=1
xi=1其余为0,注意这里是在求F(L)的最值,而不是
∑
i
∈
S
a
i
∑
i
∈
S
b
i
\frac{\sum_{i\in S}a_{i}}{\sum_{i\in S}b_{i}}
∑i∈Sbi∑i∈Sai的最值,
3.记
m
a
x
(
∑
i
∈
S
a
i
∑
i
∈
S
b
i
)
=
a
n
s
max(\frac{\sum_{i\in S}a_{i}}{\sum_{i\in S}b_{i}})=ans
max(∑i∈Sbi∑i∈Sai)=ans对L进行二分,
当maxF(L)>0的时候则有L<max,
当maxF(L)<0时,L>max,
于是根据上两条进行二分,直到找到使得max(F(L))的L,此时的L==ans
在这里我们着重解释第3步中的二分的想法是怎么来的,其余未明白部分见大佬文章
好啦下面就开始了
对第3条的分析
1.首先对,“当maxF(L)>0的时候则有L<max”,进行解释
F
(
L
)
=
∑
i
=
1
i
=
n
(
a
i
x
i
)
−
L
∑
i
=
1
i
=
n
(
b
i
x
i
)
=
C
F(L)=\sum_{i=1}^{i=n}(a_{i}x_{i})-L\sum_{i=1}^{i=n}(b_{i}x_{i})=C
F(L)=∑i=1i=n(aixi)−L∑i=1i=n(bixi)=C
我们先忘掉上述的结论,重新给出一个结论:
对于某一L,若存在序列
x
i
x_{i}
xi满足其和未n-k,且使得F(L)>0的时候则有L<max,证明如下:
F
(
L
)
=
∑
i
=
1
i
=
n
(
a
i
x
i
)
−
L
∑
i
=
1
i
=
n
(
b
i
x
i
)
=
C
>
0
F(L)=\sum_{i=1}^{i=n}(a_{i}x_{i})-L\sum_{i=1}^{i=n}(b_{i}x_{i})=C>0
F(L)=∑i=1i=n(aixi)−L∑i=1i=n(bixi)=C>0
∑
i
=
1
i
=
n
(
a
i
x
i
)
=
C
+
L
∑
i
=
1
i
=
n
(
b
i
x
i
)
\sum_{i=1}^{i=n}(a_{i}x_{i})=C+L\sum_{i=1}^{i=n}(b_{i}x_{i})
∑i=1i=n(aixi)=C+L∑i=1i=n(bixi)
∑
i
=
1
i
=
n
(
a
i
x
i
)
∑
i
=
1
i
=
n
(
b
i
x
i
)
=
C
∑
i
=
1
i
=
n
(
b
i
x
i
)
+
L
=
D
\frac{\sum_{i=1}^{i=n}(a_{i}x_{i})}{\sum_{i=1}^{i=n}(b_{i}x_{i})}=\frac{C}{\sum_{i=1}^{i=n}(b_{i}x_{i})}+L=D
∑i=1i=n(bixi)∑i=1i=n(aixi)=∑i=1i=n(bixi)C+L=D
根据上式,可以发现,存在xi使得表达式
∑
i
=
1
i
=
n
(
a
i
x
i
)
∑
i
=
1
i
=
n
(
b
i
x
i
)
\frac{\sum_{i=1}^{i=n}(a_{i}x_{i})}{\sum_{i=1}^{i=n}(b_{i}x_{i})}
∑i=1i=n(bixi)∑i=1i=n(aixi)的值D>L,于是L比目标表达式最值max要小,因为max(F(L))>F(L),若存在xi使得F(L)>0,则根据不等式传递性必有max(F(L))>F(L)>0, 并且使用max(F(L))在判断下面证明也能用到,节约了代码量!
2.接下来对"当maxF(L)<0的时候则有L>max"解释
F(L)<maxF(L)<0,则可以知道对所有
x
i
x_{i}
xi有
F
(
L
)
=
∑
i
=
1
i
=
n
(
a
i
x
i
)
−
L
∑
i
=
1
i
=
n
(
b
i
x
i
)
=
C
<
0
F(L)=\sum_{i=1}^{i=n}(a_{i}x_{i})-L\sum_{i=1}^{i=n}(b_{i}x_{i})=C<0
F(L)=∑i=1i=n(aixi)−L∑i=1i=n(bixi)=C<0,
对等式按照上面的方式进行变形
∑
i
=
1
i
=
n
(
a
i
x
i
)
∑
i
=
1
i
=
n
(
b
i
x
i
)
=
C
∑
i
=
1
i
=
n
(
b
i
x
i
)
+
L
=
D
<
L
\frac{\sum_{i=1}^{i=n}(a_{i}x_{i})}{\sum_{i=1}^{i=n}(b_{i}x_{i})}=\frac{C}{\sum_{i=1}^{i=n}(b_{i}x_{i})}+L=D<L
∑i=1i=n(bixi)∑i=1i=n(aixi)=∑i=1i=n(bixi)C+L=D<L对任意
x
i
x_{i}
xi成立,对于使得
∑
i
=
1
i
=
n
(
a
i
x
i
)
∑
i
=
1
i
=
n
(
b
i
x
i
)
\frac{\sum_{i=1}^{i=n}(a_{i}x_{i})}{\sum_{i=1}^{i=n}(b_{i}x_{i})}
∑i=1i=n(bixi)∑i=1i=n(aixi)取的最大值max得
x
i
x_{i}
xi也有max<L
有了1,2得判据,就可以根据二分法进而得出答案了.
代码如下:
#include<iostream>
#include<cmath>
#include<algorithm>
#define maxsize 1004
using namespace std;
int n,k;
double a[maxsize],b[maxsize];
bool justify(double r)
{
double d[maxsize];
for(int i=0;i<n;i++){
d[i]=a[i]-r*b[i];
// cout<<d[i]<<endl;
}
sort(d,d+n);
double sum=0;
for(int i=k;i<n;i++)sum+=d[i];
// cout<<sum<<endl;
return sum>0;
}
int main()
{
// freopen("ini","r",stdin);
while(~scanf("%d%d",&n,&k)&&(n!=0||k!=0)){
for(int i=0;i<n;i++)scanf("%lf",&a[i]);
for(int i=0;i<n;i++)scanf("%lf",&b[i]);
double l=0,r=1;
while(fabs(r-l)>1e-6)
{
double mid=(l+r)/2;
if(justify(mid))l=mid;
else r=mid;
}
int ans=(int)((r+0.005)*100);
cout<<ans<<endl;
}
return 0;
}