题意
求最优比例生成树,即令∑cost[i]/∑dis[i]=ans尽可能小,对式子略作改变化为∑cost[i]-ans×dis[i]=0。由于ans未知,所以通过0/1分数规划+Prime对∑cost[i]-s×∑dis[i]=w进行求解。
#include<bits/stdc++.h>
using namespace std;
const int mod=100000073;
const int maxn=1e3+5;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
bool vis[maxn];
int n;
double w[maxn],dis[maxn][maxn],cost[maxn][maxn];
bool prime(double s)
{
memset(vis,false,sizeof(vis));
double ans=0.0;
for(int i=1;i<=n;i++)
w[i]=cost[1][i]-s*dis[1][i];
vis[1]=true;
for(int i=1;i<n;i++)
{
int u=-1;double min1=inf;
for(int j=1;j<=n;j++)
{
if(!vis[j]&&w[j]<min1)
{
u=j;
min1=w[j];
}
}
if(u==-1)
return -1;//找不到相邻点
vis[u]=true;
ans+=min1;
for(int k=1;k<=n;k++)
{
if(!vis[k]&&cost[u][k]-s*dis[u][k]<w[k])
{
w[k]=cost[u][k]-s*dis[u][k];
}
}
}
return ans>=0.0;
}//关于返回进行范围变化的原因是所求函数单调递减
int main()
{
int x[maxn],y[maxn],z[maxn];
while(cin>>n&&n)
{
memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i]>>z[i];
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
cost[i][j]=cost[j][i]=fabs(z[i]-z[j]);
dis[i][j]=dis[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
}//处理高度与距离
double l=0.0,r=100.0;
while(r-l>0.00001)
{
double mid=(l+r)/2.0;
if(prime(mid))
l=mid;//当前结果>0.0说明取值偏小
else
r=mid;//当前结果<0.0说明取值偏大
}//二分
printf("%.3f\n",l);
}
return 0;
}