最优比率生成树 用的二分法 Dinkelbach就先留坑吧
推荐博客点击打开链接
通过构造函数
F(L)=sigma(d[i]*x[i]) 其中d[i]=a[i]-L*b[i]
我们可以知道当前的L取值是否符合条件 是否是最优解 再结合d[i]是关于L的一元单调函数 所以可以用二分法解决
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define esp 1e-5
struct node
{
double x;
double y;
double z;
};
node point[1010];
double dis[1010][1010],cost[1010][1010],w[1010][1010];
double d[1010];
double ans;
int book[1010];
int n,m;
double getdis(int u,int v)
{
double sum;
sum=sqrt((point[u].x-point[v].x)*(point[u].x-point[v].x)+(point[u].y-point[v].y)*(point[u].y-point[v].y));
return sum;
}
double getcost(int u,int v)
{
double sum;
if(point[u].z>point[v].z) sum=point[u].z-point[v].z;
else sum=point[v].z-point[u].z;
return sum;
}
void build(double l)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
w[i][j]=w[j][i]=cost[i][j]-l*dis[i][j];
}
}
return;
}
double calculate()
{
memset(book,false,sizeof(book));
memset(d,127,sizeof(d));
double ans,minn;
int i,u,v;
u=1,ans=0;
for(i=1;i<=n-1;i++)
{
book[u]=1;
for(v=1;v<=n;v++)
{
if(!book[v]&&w[u][v]<d[v])
{
d[v]=w[u][v];
}
}
minn=d[0];
for(v=1;v<=n;v++)
{
if(!book[v]&&minn>d[v])
{
minn=d[v],u=v;
}
}
if(minn==d[0])
return -1;
ans+=minn;
}
return ans;
}
void binsearch()
{
double l,r,mid;
l=0,r=100;
while(r-l>esp)
{
mid=(l+r)/2;
build(mid);
if(calculate()>esp)
{
l=mid;
}
else
{
r=mid;
ans=r;
}
}
return;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].z);
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
dis[j][i]=dis[i][j]=getdis(i,j);
cost[j][i]=cost[i][j]=getcost(i,j);
}
}
binsearch();
printf("%.3f\n",ans);
}
return 0;
}