POJ2728 Desert King(01分数规划+Prime)

题目链接

题意

求最优比例生成树,即令∑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;
}

猜你喜欢

转载自blog.csdn.net/WTMDNM_/article/details/107652723
今日推荐