4
28
2016
0

【新姿势】01分数规划

二分法:

程序框架:

L:=...;R:=...;
Repeat
  Mid:=(L+R)/2;
  For I=1..X do D[i]:=A[i]-Mid*B[i];//根据Mid计算D数组
  if 检查(Mid)成功 then L:=Mid else R:=Mid;

Until abs(L-R)<Eps;    

Dinkelbach算法:

程序框架:

L:=随便什么东西;
Repeat
  Ans:=L;
  For I=1..X do D[i]:=A[i]-L*B[i];//根据L计算D数组
  根据具体情况检查解并记录;
  p:=0;q:=0;
  for I=每一个元素 do 
     如果元素I在解中
        begin
          p:=p+A[i];q:=q+A[i];
        end;
  L:=p/q;//更新解
Until abs(Ans-L)<Eps;  

 


题目:

POJ 2976 Dropping tests

给定n个二元组(a,b),删除k个二元组,使得剩下的a元素之和与b元素之和的比率最大(比率最后乘100输出)

01分数规划的基本模型

具体分析过程见笔记/ http://www.cnblogs.com/proverbs/archive/2013/01/09/2853725.html

注意:
1、二分答案m是非严格的,这样便于判断
2、bi应当不全为0,才有意义
3、要求sigma((ai-bi*P)*xi)的最大值,可以运用贪心的思想,从大到小排序
 
对于本题来说:0 ≤ ai ≤ bi ,可以确定m的范围为[0,1]。

不太懂这句话:

To avoid ambiguities due to rounding errors, the judge tests have been constructed so that all answers are at least 0.001 away from a decision boundary (i.e., you can assume that the average is never 83.4997).

难道是说精度要求不高?

#define eps 1e-8
typedef double DB;
const int N=1000+10;
int n,K;DB l,r,mid;
struct data{
	DB a,b,c;
	bool operator <(const data &rhs)const{
		return c>rhs.c;
	}
}x[N];
bool check(DB mid)
{
	DB res=0.0;
	F(i,1,n) x[i].c=x[i].a-x[i].b*mid;
	sort(x+1,x+n+1); 
	F(i,1,n-K) res+=x[i].c;
	if(res<=0.0) return true; 
	else return false;
}	
int main()
{
	while(scanf("%d%d",&n,&K)==2 && (n||K)){//注意判断条件 
		F(i,1,n) scanf("%lf",&x[i].a);
		F(i,1,n) scanf("%lf",&x[i].b);
		DB l=0.0,r=1.0;
		while(fabs(r-l)>eps){
			DB mid=(l+r)/2.0;
			if(check(mid)) r=mid;
			else l=mid;
		}
		printf("%.0lf\n",l*100);
	}
	return 0;
}

 

Category: 分数规划 | Tags: 二分 分数规划 | Read Count: 797

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com