什么是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.