zoukankan      html  css  js  c++  java
  • 【POJ2728】沙漠王国Desert King-最优比率生成树-01分数规划

    Description

    大卫刚被选举为沙漠王国的国王。为了赢得人们的尊重,他决定修建渠道,把水引到整个国家的每个村庄。使得连接到中心村庄的所有村庄都将会被灌溉。经过多天的研究,他最终制定出目的。就是使建造渠道每英里的平均价格最小。换句话说,建造渠道的总体成本与总长度的比值必须最小。只需要建立必须的渠道,把水引到所有的村庄即可。也就是每个村庄仅一种方式连接到中心村庄。
      已知每个村庄的位置和高度,任意两个村庄之间的渠道必须是直的。长度为这两个村庄(x1,y1)和(x2,y2)之间的距离sqrt((x1-x2)2+(y1-y2)2),建立渠道的花费为这两个村庄高度差的绝对值。每个村庄都在不同高度,注意水能够通过特殊的设备从低处流到高处(不考虑设备费用),没有任意三个村庄位于同一条水平线上。现在国王想知道建造渠道每英里的平均价格最小是多少?

    Input

    输入有多组测试数据;
      每组测试数据第一行包含一个整数N(2<=N<=1000),表示村庄的个数。
      接下来n行,每行三个整数x,y和z(0<=x,y<10000,0<=z<10000000),表示一个村庄位于(x,y)这点,高度为z,文件最后一行以一个0作为结束,不用处理。

    Output

    对于每组测试数据,输出一行为建造渠道的总体成本与总长度的比值,保留三位小数。

    Sample Input

    4
    0 0 0
    0 1 1
    1 1 2
    1 0 3
    0

    Sample Output

    1.000


    思路

    • 最优比率生成树(01分数规划运用实例)
    • 完全图用prim
    • 标准上界应该为high之和/min(dis),但1e5也能过

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    int n,flag[1005];
    double dis[1005][1005],high[1005][1005],d[1005];
    struct fdfdfd{double x,y,z;}e[1005];
    double js(int i,int j){return sqrt((e[i].x-e[j].x)*(e[i].x-e[j].x)+(e[i].y-e[j].y)*(e[i].y-e[j].y));}
    bool prim(double x)
    {
    	double sum=0;
    	memset(flag,0,sizeof(flag));
    	memset(d,0x7f,sizeof(d)); d[1]=0;
    	for(int i=1;i<=n;++i)
    	{
    		double minn=0x7fffffff; int k=-1;
    		for(int j=1;j<=n;++j)
    			if(!flag[j]&&d[j]<minn) minn=d[j],k=j;
    		flag[k]=1; sum+=d[k];
    		for(int j=1;j<=n;++j)
    			if(!flag[j]) d[j]=min(d[j],high[k][j]-x*dis[k][j]);
    	}
    	return (sum>0);
    }
    int main()
    {
    	while(scanf("%d",&n))
    	{
    		if(!n) break;
    		for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&e[i].x,&e[i].y,&e[i].z);
    		for(int i=1;i<=n;++i)
    			for(int j=i+1;j<=n;++j)
    			{
    				dis[i][j]=dis[j][i]=js(i,j);
    				high[i][j]=high[j][i]=fabs(e[i].z-e[j].z);
    			}
    		double l=0,r=100000;
    		while(r-l>1e-8)
    		{
    			double mid=(r+l)/2.0;
    			if(prim(mid)) l=mid;
    			else r=mid;
    		}
    		printf("%.3f
    ",l);
    	}
    	return 0;
    }
    
  • 相关阅读:
    request常用的方法
    JS通过正则限制 input 输入框只能输入整数、小数(金额或者现金)
    基于云原生的秒杀系统设计思路
    html<input>输入框中各种正则表达式设置
    cursor:hand与cursor:pointer的区别介绍
    读入/输出优化
    手动扩栈,防止溢出
    快速乘(O(1))
    二分图若干性质
    康拓展开
  • 原文地址:https://www.cnblogs.com/wuwendongxi/p/13597202.html
Copyright © 2011-2022 走看看