Desert King
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 22717   Accepted: 6374

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
题解:先是超时,然后wa,最小生成树生疏了。。。
这个就是01分数规划的变形,即找到K求hi-li*K的最小生成树使得k最小;

有N个村庄,给出每个村庄的坐标和海拔,,benifit为两点之间的距离,cost为两点的高度差,现在要求一棵树使得 cost / benift 最小,即求一个最优比例生成树

第一次遇见这种生成树,在网上找了个解法

假设sigma(h)/sigma(l)==K 均值K可取,即: sigma(h)==K*sigma(l)

sigma(h)==K*(l1+l2+l3+...lm)

sigma(h)==K*l1+K*l2+K*l3+...K*lm

把原来的每个边的h都减去K*l

即hi'=hi-li'==hi-li*K

然后问题可以转换到求hi'这些边的最小生成树了

如果hi'这些边得最小生成树权值和<=0.0,说明K这个均值可取

对于k,二分求解即可

代码:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
const int MAXN=;
double vis[MAXN],low[MAXN];
int N;
double R;
struct Node{
double x,y,h;
};
Node dt[MAXN];
double len[MAXN][MAXN],cost[MAXN][MAXN];
double getl(Node a,Node b){
double x=b.x-a.x,y=b.y-a.y;
return sqrt(x*x+y*y);
} bool prime(){
double total;
mem(vis,);
for(int i=;i<N;i++)low[i]=cost[][i]-R*len[][i];
total=;
vis[]=;//0没有被标记为1。。。错了半天;
for(int i=;i<N;i++){
double temp=INF;
int k;
for(int j=;j<N;j++)
if(!vis[j]&&low[j]<temp)temp=low[j],k=j;
if(temp==INF)break;
total+=temp;
vis[k]=;
for(int j=;j<N;j++)
if(!vis[j]&&low[j]>cost[k][j]-R*len[k][j])low[j]=cost[k][j]-R*len[k][j];
}
//printf("total=%lf R=%lf\n",total,R);
if(total>)return true;
else return false;
}
int main(){
while(scanf("%d",&N),N){
mem(len,INF);
mem(cost,INF);
double mxl=-INF,mil=INF,mxc=-INF,mic=INF;
for(int i=;i<N;i++)
scanf("%lf%lf%lf",&dt[i].x,&dt[i].y,&dt[i].h); for(int i=;i<N;i++){
for(int j=i+;j<N;j++){
len[j][i]=len[i][j]=getl(dt[i],dt[j]);
cost[j][i]=cost[i][j]=abs(dt[i].h-dt[j].h);
mxl=max(mxl,len[i][j]);
mxc=max(mxc,cost[i][j]);
mil=min(mil,len[i][j]);
mic=min(mic,cost[i][j]);
}
}
//printf("%lf %lf %lf %lf\n",mil,mic,mxl,mxc);
double l=mic/mxl,r=mxc/mil;//要是从0到mx会超时; // printf("%lf %lf\n",l,r);
while(r-l>1e-){
R=(l+r)/;
if(prime())l=R;
else r=R;
}
printf("%.3f\n",l);
}
return ;
}

Desert King(最优比率生成树)的更多相关文章

  1. POJ 2728 Desert King 最优比率生成树

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20978   Accepted: 5898 [Des ...

  2. 【POJ2728】Desert King 最优比率生成树

    题目大意:给定一个 N 个点的无向完全图,边有两个不同性质的边权,求该无向图的一棵最优比例生成树,使得性质为 A 的边权和比性质为 B 的边权和最小. 题解:要求的答案可以看成是 0-1 分数规划问题 ...

  3. POJ2728 Desert King —— 最优比率生成树 二分法

    题目链接:http://poj.org/problem?id=2728 Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Subm ...

  4. POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)

    题目链接 \(Description\) 将n个村庄连成一棵树,村之间的距离为两村的欧几里得距离,村之间的花费为海拔z的差,求花费和与长度和的最小比值 \(Solution\) 二分,假设mid为可行 ...

  5. POJ2728 Desert King 最优比率生成树

    题目 http://poj.org/problem?id=2728 关键词:0/1分数规划,参数搜索,二分法,dinkelbach 参考资料:http://hi.baidu.com/zzningxp/ ...

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

    题意: 给定n个村子的坐标(x,y)和高度z, 求出修n-1条路连通所有村子, 并且让 修路花费/修路长度 最少的值 两个村子修一条路, 修路花费 = abs(高度差), 修路长度 = 欧氏距离 分析 ...

  7. POJ 2728 Desert King (最优比率树)

    题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目 ...

  8. poj-2728Desert King(最优比率生成树)

    David the Great has just become the king of a desert country. To win the respect of his people, he d ...

  9. POJ 2728 Desert King (最优比例生成树)

    POJ2728 无向图中对每条边i 有两个权值wi 和vi 求一个生成树使得 (w1+w2+...wn-1)/(v1+v2+...+vn-1)最小. 采用二分答案mid的思想. 将边的权值改为 wi- ...

随机推荐

  1. 浅谈SpringMVC(二)

    一.SpringMVC的拦截器 1.写类implements HandlerInterceptor public class MyMvcInterceptor implements HandlerIn ...

  2. Hadoop学习之YARN框架

    转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/,非常感谢分享! 对于业界的大数据存储及分布式处理系统来说,H ...

  3. Struts学习之类型转换

    * 从页面中获取对应的内容        * 在动作类action中,声明与页面中表单name属性的值同名的属性        * 提供get和set方法        * struts2框架就会通过 ...

  4. adb wifi连接手机

    1. 默认情况下,ADB是通过USB来进行连接的. 不需要USB线,直接在android设备上安装一个超级终端,在终端里运行以下代码即可: su setprop service.adb.tcp.por ...

  5. VirtualBox 中ubuntu访问window下共享目录

    1,vbox中设置window需要共享给vbox中ubuntu的文件夹,主要要注意共享文件夹名称windowShare. 2,在ubuntu中挂载windowShare. sudo mount -t ...

  6. Android 常用动画小结

    1. 渐入动画 // Request the next activity transition (here starting a new one). startActivity(new Intent( ...

  7. halcon与C#混合编程进阶版

    这篇主要是C#和Halcon的混合编程,在此基础上对按键不同功能的划分,以及图片适应窗口和从本地打开图片. 新手来这里:http://www.cnblogs.com/badguy518/p/55150 ...

  8. C 查找子字符串

    自己用 C 写的一个查找子字符串的函数 int findstr(char *str,char *substr) //C实现 find{ if(NULL == str || NULL== substr) ...

  9. Windows phone 8.1 MessageBox 变了哦!

    using Windows.UI.Popups; public async void MessageBoxShow(string content, string caption) { MessageD ...

  10. windows7下,protel 99se元件库加载问题的解决方案

    方法一:到C盘(系统盘),系统文件夹(c:\windows)下的ADVPCB99SE和ADVSch99SE文件先配置原理图,用本文打开ADVPCB99SE文件,在[Change Library Fil ...