Desert King
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 21766   Accepted: 6087

Description

David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his country to bring water to every village. Villages which are connected to his capital village will be watered. As the dominate ruler and the symbol of wisdom in the country, he needs to build the channels in a most elegant way.

After days of study, he finally figured his plan out. He wanted the average cost of each mile of the channels to be minimized. In other words, the ratio of the overall cost of the channels to the total length must be minimized. He just needs to build the necessary channels to bring water to all the villages, which means there will be only one way to connect each village to the capital.

His engineers surveyed the country and recorded the position and altitude of each village. All the channels must go straight between two villages and be built horizontally. Since every two villages are at different altitudes, they concluded that each channel between two villages needed a vertical water lifter, which can lift water up or let water flow down. The length of the channel is the horizontal distance between the two villages. The cost of the channel is the height of the lifter. You should notice that each village is at a different altitude, and different channels can't share a lifter. Channels can intersect safely and no three villages are on the same line.

As King David's prime scientist and programmer, you are asked to find out the best solution to build the channels.

Input

There are several test cases. Each test case starts with a line containing a number N (2 <= N <= 1000), which is the number of villages. Each of the following N lines contains three integers, x, y and z (0 <= x, y < 10000, 0 <= z < 10000000). (x, y) is the position of the village and z is the altitude. The first village is the capital. A test case with N = 0 ends the input, and should not be processed.

Output

For each test case, output one line containing a decimal number, which is the minimum ratio of overall cost of the channels to the total length. This number should be rounded three digits after the decimal point.

Sample Input

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

Sample Output

1.000
题意:有n个村庄,分别给出每个村庄的地理坐标(xi,yi)和海拔hi,要求在村庄之间修一些河道,使这些河道联通所有的村庄,不同的村庄由于海拔的差异需要修水泵,每个水泵的费用为这两个村庄的海拔差值,且每个水泵为一条河道所用,要求所有的费用/总的河道长度比率最小
分析:r=sigma(h[i][j])/sigma(l[i][j]),设R为最优值,则r>=R;(h[i][j]代表修每条河道的费用,l[i][j]代表每条河道的长度,sigma()为生成树里面的边)
即:sigma(h[i][j])/sigma(l[i][j])>=R,所以:h[r]=sigma(h[i][j])-r*sigma(l[i][j])>=0;
所以对于每一个r对应的h(r)的最小生成树>=0
当h(r)<0的时候减小r的值,否则增大r的值,逐渐二分使h(r)=0即可;
方法一:二分法
#include"stdio.h"
#include"string.h"
#include"math.h"
#define inf 0x3f3f3f3f
#define M 2009
#define eps 1e-7
struct node
{
int x,y,h;
}p[M];
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
}
double dis[M],G[M][M],L[M][M];
int use[M];
double dij(int n,int s)
{
double sum=0;
memset(use,0,sizeof(use));
for(int i=1;i<=n;i++)
dis[i]=inf;
dis[s]=0;
for(int i=1;i<=n;i++)
{
double mini=inf;
int id=-1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]<mini)
{
mini=dis[j];
id=j;
}
}
if(id==-1)break;
sum+=dis[id];
use[id]=1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]>G[id][j])
dis[j]=G[id][j];
}
}
return sum;
}
double solve(int n,double r)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
G[i][j]=G[j][i]=fabs(p[i].h*1.0-p[j].h*1.0)-L[i][j]*r+1000000000.0;
}
return dij(n,1)-(n-1)*1000000000.0;
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
double l=0,r=0,mid;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].h);
r+=p[i].h;
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
L[i][j]=L[j][i]=dist(p[i],p[j]);
}
}
while(r-l>eps)
{
mid=(l+r)/2;
double msg=solve(n,mid);
if(msg<0)
{
r=mid;
}
else
{
l=mid;
}
}
printf("%.3lf\n",r);
}
return 0;
}

  方法二:迭代法

#include"stdio.h"
#include"string.h"
#include"math.h"
#define inf 0x3f3f3f3f
#define M 2009
#define eps 1e-6
struct node
{
int x,y,h;
}p[M];
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
}
double dis[M],G[M][M],L[M][M];
int use[M],pre[M];
double dij(int n,int s)
{
double sum=0,cost=0,leng=0;
memset(use,0,sizeof(use));
for(int i=1;i<=n;i++)
{
dis[i]=inf;
pre[i]=-1;
}
dis[s]=0;
for(int i=1;i<=n;i++)
{
double mini=inf;
int id=-1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]<mini)
{
mini=dis[j];
id=j;
}
}
if(id==-1)break;
sum+=dis[id];
use[id]=1;
if(pre[id]!=-1)
{
cost+=fabs(p[id].h*1.0-p[pre[id]].h);
leng+=L[id][pre[id]];
}
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]>G[id][j])
{
dis[j]=G[id][j];
pre[j]=id;
}
}
}
return cost/leng;
}
double solve(int n,double r)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
G[i][j]=G[j][i]=fabs(p[i].h*1.0-p[j].h*1.0)-L[i][j]*r+1000000000.0;
}
}
return dij(n,1);
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].h);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
L[i][j]=L[j][i]=dist(p[i],p[j]);
double x0=0,x;
while(1)
{
x=solve(n,x0);
if(fabs(x-x0)<eps)
break;
x0=x;
}
printf("%.3lf\n",x);
}
return 0;
}

  

01分数规划poj2728(最优比例生成树)的更多相关文章

  1. POJ 2728 Desert King 01分数规划,最优比率生成树

    一个完全图,每两个点之间的cost是海拔差距的绝对值,长度是平面欧式距离, 让你找到一棵生成树,使得树边的的cost的和/距离的和,比例最小 然后就是最优比例生成树,也就是01规划裸题 看这一发:ht ...

  2. POJ 3621 Sightseeing Cows 01分数规划,最优比例环的问题

    http://www.cnblogs.com/wally/p/3228171.html 题解请戳上面 然后对于01规划的总结 1:对于一个表,求最优比例 这种就是每个点位有benefit和cost,这 ...

  3. 【转】[Algorithm]01分数规划

    因为搜索关于CFRound277.5E题的题解时发现了这篇文章,很多地方都有值得借鉴的东西,因此转了过来 原文:http://www.cnblogs.com/perseawe/archive/2012 ...

  4. POJ 2976 Dropping tests 01分数规划 模板

    Dropping tests   Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6373   Accepted: 2198 ...

  5. 【poj 2976】Dropping tests(算法效率--01分数规划 模版题+二分){附【转】01分数规划问题}

    P.S.又是一个抽时间学了2个小时的新东西......讲解在上半部分,题解在下半部分. 先说一下转的原文:http://www.cnblogs.com/perseawe/archive/2012/05 ...

  6. [转]01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环

    01分数规划 前置技能 二分思想最短路算法一些数学脑细胞? 问题模型1 基本01分数规划问题 给定nn个二元组(valuei,costi)(valuei,costi),valueivaluei是选择此 ...

  7. POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)

    [题意]每条路径有一个 cost 和 dist,求图中 sigma(cost) / sigma(dist) 最小的生成树. 标准的最优比率生成树,楼教主当年开场随手1YES然后把别人带错方向的题Orz ...

  8. POJ2728 最小比率生成树/0-1分数规划/二分/迭代(迭代不会)

    用01分数规划 + prime + 二分 竟然2950MS惊险的过了QAQ 前提是在TLE了好几次下过的 = = 题目意思:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一 ...

  9. POJ 2728 Desert King(最优比率生成树 01分数规划)

    http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简 ...

随机推荐

  1. javascript:void(0)与#整理

    window.location.href="/signup/devicelogin.shtml"; 指跳转到引号的url地址 #包含了一个位置信息,默认的锚点#是top,网页的顶端 ...

  2. Delphi 如何清除动态数组的内存?

    SetLength(glb_IndexConfig,); FreeAndNil(glb_IndexConfig);

  3. 图片放大方法、、菜单栏的位置随滚轮移动固定方法、、<a></a>去外层虚线方法:a:focus { outline:none; -moz-outline:none;};

    图片放大方法一: <style type="text/css">.xt{ width:230px; height:230px;}.tp{ width:230px; he ...

  4. JVM GC (一)

    1. 先来说GC工作在哪块区域呢? 程序计数器,虚拟机栈(也就平时所说的栈), 本地方法栈这三区域随着线程而生,随着线程而灭,出栈入栈的操作,在栈中分配配的多少内存都具 有确定性,在这几个区域就不用考 ...

  5. Qt编写自定义控件大全(liudianwu)

    http://www.cnblogs.com/feiyangqingyun/p/6128288.html http://www.qtcn.org/bbs/read-htm-tid-62279.html

  6. 自己diy一个jquery分页插件

    js基础学习过程中,期间经历换工作的各种面试,很多面试官问过:有没有写过jquery插件?等类似问题. 就个人而言,关于jquery插件的文章确实看过不少,但是一直没有动手写一个,一是不想在目前学习j ...

  7. PushKit和传统长连接方式的比较

    iOS and PushKit This post will cover basic concepts for VoIP apps on iOS. I will not post any code ( ...

  8. [LeetCode]题解(python):032-Longest Valid Parentheses

    题目来源 https://leetcode.com/problems/longest-valid-parentheses/ Given a string containing just the cha ...

  9. Android开发笔记-加载xml资源

    1.Activity获取strings.xml中键的值 需要通过 getResources().getString(R.string.*)方法获得 以“state”为例 String value= g ...

  10. 关于action script与js相互调用的Security Error问题

    大家都知道,as和js相互调用可以通过ExternalInterface.call和ExternalInterface.addCallback来进行. 比较好的做法是使用之前通过ExternalInt ...