01分数规划poj2728(最优比例生成树)

时间:2022-09-02 08:20:33
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. 【转】&lbrack;Algorithm&rsqb;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分数规划 模版题&plus;二分){附【转】01分数规划问题}

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

  6. &lbrack;转&rsqb;01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环

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

  7. POJ 2728 Desert King &starf;&lpar;01分数规划介绍 && 应用の最优比率生成树&rpar;

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

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

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

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

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

随机推荐

  1. 更改XAMPP中MySQL数据库的端口号

    更改XAMPP中MySQL数据库的端口号 如果电脑上已安装MySql数据库,还想用XAMPP中自带的数据库就需要更改XAMPP中数据库的端口号,避免和已安装的数据库冲突.本例以更改为3307端口号为例 ...

  2. &lpar; 译、持续更新 &rpar; JavaScript 上分小技巧&lpar;四&rpar;

    后续如有内容,本篇将会照常更新并排满15个知识点,以下是其他几篇译文的地址: 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第二篇地址:( 译.持续更新 ) JavaScr ...

  3. &lbrack;Zz&rsqb; DX depth buffer

    声明:本文完全翻译自DX SDK Documentation depth buffer,通常被称为z-buffer或者w-buffer,是设备的一个属性,用来存储深度信息,被D3D使用.当D3D渲染一 ...

  4. BlockingQueue接口

    BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会阻塞,当容量为空时取元素操作会阻塞 ...

  5. ubuntu12&period;04 安装 ruby1&period;9&period;3

    sudo apt-add-repository ppa:brightbox/ruby-ng sudo apt-get update sudo apt-get install ruby rubygems ...

  6. jquery去除字符串首尾空格的方法:&dollar;&period;trim&lpar;&rpar;

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. python科学计算&lowbar;numpy&lowbar;ndarray

    ndarray:n-dimensional array object,即多维数组对象,是python自带的array对象的扩展,array对象和list对象的区别是array对象的每一个元素都是数值, ...

  8. codeforces659C

    Tanya and Toys CodeForces - 659C In Berland recently a new collection of toys went on sale. This col ...

  9. ThinkPad T420 Fn&plus;F5

    关于F5,可做如下设置:     1)官网win7系统下载SIhotkey[8jvu39ww].exe:最新版本的我没测试,应该也可以用.     2)双击安装,并按程序安装,直到要你选择安装on s ...

  10. opencv 学习资料

    [视觉与图像]OpenCV篇:Python+OpenCV实用教程 Python+OpenCV教程15:直方图