01分数规划学习笔记

01分数规划学习笔记

今天 gsh 带着我们复习了一下01分数规划。

01分数规划就是假设一个物体有两个属性 a,b,同时选择在这个集合中的k个物品,使:

[v=dfrac{sum^{i=1} _{i<=n} a_i cdot x_i}{sum ^{i=1} _{i<=n} b_i cdot x_i} ,sum_{i=1}^{n}x_i=k ]

的值最大。

那么如何能做到呢?看这个式子我们很难看出如何求解,那么将其变形。

[v cdot sum^{i=1} _{i<=n} b_i cdot x_i- sum^{i=1}_{i<=n} a_icdot x_i=0 ]

提取公因式

[sum ^{i=1}_{i<=n} x_i cdot(vcdot b_i-a_i)=0 ]

那么,我们可以二分一个v,设一个变量

[c_i=(vcdot b_i-a_i) ]

sort后选择最大的k个,二分如下。

	while(r-l>1e-5) {
			double mid=(l+r)/2;
			if(check(mid))
				l=mid;
			else r=mid;
		}

然后就有最优比率生成环(用spfa等等判正环),最优比率生成树(最大生成树)求出sumc是否大于0即可。

附一道题,poj2728,Desert King,最优比率生成树。

题目大意:有n个村庄,每个村庄有一个高度和坐标,要求建一个生成树,每条边有两个属性是距离与代价,要求单位长度的花费最小 (代价的大小就是这两个村庄的高度差的绝对值)。

//Writer : Hsz %WJMZBMR%tourist%hzwer
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
int n;
const int N=1004;
int x[N],y[N],z[N];
bool vis[N];
double a[N][N],b[N][N],c[N][N],dis[N];//邻接矩阵存图。
double dist(int d,int e) {
	return (x[d]-x[e])*(x[d]-x[e])+(y[d]-y[e])*(y[d]-y[e]);
}
bool check(double v) {
	memset(vis,0,sizeof vis);
	vis[1]=1;
	for(int i=1; i<=n; i++) dis[i]=b[1][i]-v*a[1][i];
	double ans=0;
	for(int i=2; i<=n; i++) {//prim求最小生成树
		double tp=1061109567;
		int k;
		for(int j=2; j<=n; j++)
			if(!vis[j] and dis[j]<tp) k=j,tp=dis[j];
		if(k==-1) break;
		vis[k]=1;
		ans+=tp;
		for(int j=2; j<=n; j++) {
			if(!vis[j] and b[k][j]-v*(a[k][j])<dis[j]) {
				dis[j]=b[k][j]-v*(a[k][j]);
			}
		}
	}
	return ans>=0;
}
int main() {
	while(~scanf("%d",&n)&&n) {
		for(int i=1; i<=n; i++) {
			scanf("%d%d%d",&x[i],&y[i],&z[i]);
		}
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++)
				if(i!=j)
					a[i][j]=sqrt(dist(i,j)),b[i][j]=abs(z[i]-z[j]);
		double l=0,r=1e9;
		while(r-l>1e-5) {//二分
			double mid=(l+r)/2;
			if(check(mid))
				l=mid;
			else r=mid;
		}
		printf("%.3lf
",l);
	}

	return 0;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9094398.html