0/1分数规划
求下式的最大值:
\[\frac{\sum_i^n a_i \times x_i}{\sum_i^n b_i \times x_i}
\]
也就是 对任意的x
\[\frac{\sum_i^n a_i \times x_i}{\sum_i^n b_i \times x_i} \le ans
\]
二分一个值mid 问题转化是否存在一组x 使
\[\sum_i^n (a_i -b_i \times mid ) \times x_i \ge 0
\]
如果存在 说明二分的值小了 如果不存在 说明二分的值大了
所以一求上面式子的最大值即可
这是0/1分数规划问题的关键: 求出满足题意的最大值
最优比例生成树
每个边有连个权值 求最优比例生成树
沙漠之王
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=1010;
const int INF=0x3f3f3f3f;
const double eps=1e-6;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int n;
struct Point
{
int x,y,h;
}p[N];
double a[N][N],b[N][N],e[N][N];
double getdis(int x,int y,int x_,int y_){ return sqrt( (x-x_)*(x-x_)+(y-y_)*(y-y_) ); }
double dis[N];
bool vis[N];
//稠密图还真的不能加堆优化 加上堆优化后变成mlogn prim的优势不再显著
//double:: 1e37
bool check(double mid)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
e[i][j]=a[i][j]-mid*b[i][j];
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
dis[1]=0;
for(int i=1;i<=n;i++)
{
int x=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&(!x||dis[j]<dis[x])) x=j;//这种查找方式一定要处理第一次查找的情况
vis[x]=1;
for(int j=1;j<=n;j++)
if(!vis[j]) dis[j]=min(dis[j],e[x][j]);
}
double ret=0;
for(int i=1;i<=n;i++) ret+=dis[i];
return ret<0;
}
int main()
{
while( (n=read())!=0)
{
for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read(),p[i].h=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=abs(p[i].h-p[j].h);
b[i][j]=getdis(p[i].x,p[i].y,p[j].x,p[j].y);
}
double l=0,r=1e11;
while(r-l>eps)
{
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.3lf\n",r);
}
return 0;
}

浙公网安备 33010602011771号