题目大意:
给出 n , a [ ] n,a[] n,a[]和 b [ ] b[] b[],求在满足 ∑ i = 1 n x i = m \sum^{n}_{i=1}x_i=m ∑i=1nxi=m时 m a x { ∑ i = 1 n a i × x i ∑ i = 1 n b i × x i } max\{\frac{\sum^{n}_{i=1}a_i\times x_i}{\sum^{n}_{i=1}b_i\times x_i}\} max{∑i=1nbi×xi∑i=1nai×xi}。
思路:
0
/
1
0/1
0/1分数规划裸体。
推荐参考《算法竞赛进阶指南》
P
181
P181
P181。
随便取一个数
L
L
L,判断是否有一组
x
[
]
x[]
x[]满足
∑
i
=
1
n
(
a
i
−
L
×
b
i
)
≥
L
\sum^{n}_{i=1}(a_i-L\times b_i)\geq L
∑i=1n(ai−L×bi)≥L。
若有,那么变形得
(
∑
i
=
1
n
a
i
×
x
i
)
−
L
×
(
∑
i
=
1
n
b
i
×
x
i
≥
0
)
(\sum^{n}_{i=1}a_i\times x_i)-L\times(\sum^{n}_{i=1}b_i\times x_i\geq 0)
(∑i=1nai×xi)−L×(∑i=1nbi×xi≥0)。则
∑
i
=
1
n
a
i
×
x
i
∑
i
=
1
n
b
i
×
x
i
≥
L
\frac{\sum^{n}_{i=1}a_i\times x_i}{\sum^{n}_{i=1}b_i\times x_i}\geq L
∑i=1nbi×xi∑i=1nai×xi≥L。
所以答案就不小于
L
L
L,否则答案就小于
L
L
L。
那么就二分
L
L
L,知道精度小于
1
0
−
3
10^{-3}
10−3为止。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=100010;
int n,m;
double l,r,mid;
struct node
{
int a,b;
double s;
}a[N];
bool cmp(node x,node y)
{
return x.s>y.s;
}
bool check() //判断最大的m个之和是否大于L
{
double sum=0.0;
for (int i=1;i<=m;i++)
sum+=a[i].s;
return sum>=0;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i].a);
for (int i=1;i<=n;i++)
scanf("%d",&a[i].b);
l=0.0001;
r=20000.0;
while (r-l>=0.0001) //二分L
{
mid=(l+r)/2.0;
for (int i=1;i<=n;i++)
a[i].s=(double)a[i].a/mid-(double)a[i].b;
sort(a+1,a+1+n,cmp);
if (check()) l=mid;
else r=mid;
}
printf("%0.3lf\n",l);
return 0;
}