01分数规划

[01分数规划]【学习笔记】

1.裸

  • [POJ2976]Dropping tests
    题目大意:给出序列\(a,b\)求,去掉任意\(k\)个对应的\(a_i, b_i\)使得剩下的\(100*\frac{\sum_{i=1}^{n-k}a_i}{\sum_{i=1}^{n-k}b_i}\)最大,求这个最大值
bool check(double mid){
	for(int i=1; i <= n; i++) c[i]=100*a[i]-mid*b[i];
	sort(c+1, c+1+n); double sum=0;
	for(int i=1; i <= k; i++) sum+=c[n-i+1];//这里的k为n-k
	return sum > 0;
}
double eps=1e-4;
void cal(){
	double l=0.0, r=100.0;
	while(r-l > eps) {double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid;} 
	printf("%.0f\n", l);
}

2.最优比率生成图

  • [POJ2728]Desert King
    (我不会说我是现学的prime)
    题目大意:给出有\(N\)个点的无向图,每个点有一个海拔高度,任意两点间连有一条边,边长\(R_e\)为两点间的水平距离,边权为\(C_e\),求此图的生成树\(G\),使得\(\sum_{e\in G}C_e/R_e\)最小,输出这个最小值
    \(W_e=R_e\times ans-C_e\),二分\(ans\),只要\(\forall G\)使得\(\sum_{e\in G}W_e >= 0\) 那么,这个\(ans\)就是可行解,则求图的最大生成树即可
bool check(double mid){
	for(int i=1; i <= n; i++) for(int j=i+1; j <= n; j++) 
		w[i][j]=w[j][i]=mid*len[i][j]-cost[i][j];
	double sum=0; memset(vis, 0, sizeof(vis)); memset(d, -0x3f3f3f3f, sizeof(d)); d[1]=0;
	for(int i=1; i < n; i++){
		int x=0;
		for(int j=1; j <= n; j++) if(!vis[j] && (!x || d[j] > d[x])) x=j;
		vis[x]=1;
		for(int j=1; j <= n; j++) if(!vis[j]) d[j]=max(d[j], w[x][j]);
	}
	for(int i=2; i <= n; i++) sum+=d[i];
	return sum > 0;
}
double eps=1e-6;
void cal(){
	double l=0.0, r=100; 
	while(r-l > eps){
		double mid=(l+r)/2;
		if(check(mid)) r=mid; else l=mid;
	}
	printf("%.3f\n", l);
}
posted @ 2018-07-10 10:16  zerolt  阅读(126)  评论(0编辑  收藏  举报