书P368
题目地址:https://ac.nowcoder.com/acm/contest/1056/C
① 0/1分数规划https://blog.nowcoder.net/n/70ad985a57bc4085aaee4d40fd2a9451
② Prim算法https://blog.nowcoder.net/n/012b92baab1f4ee59bb17b9bcb8dadb4
#include<bits/stdc++.h>
using namespace std;
const double inf=1e18;
const int N=15e4+10;
const int maxn=1e3+10;
const double eps=1e-5;
int n;
double cost[maxn][maxn],dis[maxn][maxn],x[maxn],y[maxn],z[maxn];
int vis[maxn];
double get_dis(int a,int b)
{
return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));//求两点间距离
}
int check(double x)//Prim算法求最大生成树边权之和是否非负
{
memset(vis,0,sizeof(vis));
double sum=0,lowcost[maxn];
for(int i=1;i<=n;i++)
{
lowcost[i]=cost[1][i]-x*dis[1][i];
}
for(int i=2;i<=n;i++)
{
double temp=inf;
int k=-1;
for(int j=2;j<=n;j++)
{
if(!vis[j]&&lowcost[j]<temp)
{
k=j;
temp=lowcost[j];
}
}
if(k==-1)
{
break;
}
vis[k]=1;
sum+=temp;
for(int j=2;j<=n;j++)
{
if(!vis[j]&&cost[k][j]-x*dis[k][j]<lowcost[j])
{
lowcost[j]=cost[k][j]-x*dis[k][j];
}
}
}
if(sum>=0)return 1;
return 0;
}
int main()
{
while(cin>>n&&n!=0)
{
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i]>>z[i];
}
for(int i=1;i<=n-1;i++)
{
for(int j=i+1;j<=n;j++)
{
dis[i][j]=dis[j][i]=get_dis(i,j);//转化为无向图中的收益与代价
cost[i][j]=cost[j][i]=abs(z[i]-z[j]);
}
}
double l=0.0,r=100.0;
while(r-l>=eps)
{
double mid=(l+r)/2;
if(check(mid))//判断mid比答案大还是小
{
l=mid;
}
else
{
r=mid;
}
}
printf("%.3f\n",r);
}
return 0;
} 
京公网安备 11010502036488号