什么是01分数规划:
给出n个分数ai/bi,选出m个(m<=n)使得∑(ai)/∑(bi){其中i是被选出的分数编号}达到最大值。
01 分数规划的两种方法:
1、二分法
二分一个答案k,令ci=ai-k*bi,并将ci排序,选出最大的m个,如果∑(ci){1<=i<=m}>=0,那么提高答案k的下界,否则降低上界,直到k的精度满足要求为止。
2、Dinkelbach迭代法
随意构造一个答案k,令ci=ai-k*bi,并将ci排序,选出最大的m个,令q=∑(ai)/∑(bi){1<=i<=m}与k的差在精度范围内就输出,否则令k=q,直至满足精度要求。
总结:
两种方法各有利弊,二分法精度较高,容易理解和证明,然而速度较慢。而Dinkelbach迭代法速度较快,但精度低,不易理解和证明。可视情况选择解题方法。
给出本题的代码(Dinkelbach迭代法):
Program Dropping_Tests;//By_Thispoet
Const
maxn=1000;
Var
i,m,n :Longint;
j,p :Int64;
k,q :Extended;
a,b :Array[1..maxn]of Int64;
c :Array[1..maxn]of Extended;
Procedure Qsort(l,r:Longint);
var i,j :Longint;
tmp :Int64;
k,temp :Extended;
begin
i:=l;j:=r;k:=c[(i+j)>>1];
repeat
while c[i]>k do inc(i);
while c[j]<k do dec(j);
if i<=j then
begin
tmp:=a[i];a[i]:=a[j];a[j]:=tmp;
tmp:=b[i];b[i]:=b[j];b[j]:=tmp;
temp:=c[i];c[i]:=c[j];c[j]:=temp;
inc(i);dec(j);
end;
until i>j;
if l<j then Qsort(l,j);
if i<r then Qsort(i,r);
end;
BEGIN
readln(n,m);
while not ((n=0)and(m=0)) do
begin
m:=n-m;
for i:=1 to n do read(a[i]);readln;
for i:=1 to n do read(b[i]);readln;
q:=0.5;
repeat
k:=q;
j:=0;p:=0;
for i:=1 to n do c[i]:=a[i]-b[i]*k;
Qsort(1,n);
for i:=1 to m do
begin
inc(j,a[i]);
inc(p,b[i]);
end;
q:=j/p;
until abs(k-q)<=0.00001;
writeln(round(100*k));
readln(n,m);
end;
END.