题目链接

\(Description\)

将n个村庄连成一棵树,村之间的距离为两村的欧几里得距离,村之间的花费为海拔z的差,求花费和与长度和的最小比值

\(Solution\)

二分,假设mid为可行的某一生成树的解,则应有 \((∑cost)/(∑dis) = mid\)

变形得 \(\sum(cost-mid*dis) = 0\)

取cost-mid*dis为边权,Prim求最小生成树(即尽可能满足mid)

若\(\sum(cost-mid*dis) > 0\),说明怎么也满足不了mid,mid不是可行解 偏小;若 < 0,则存在某些生成树满足条件,还可以更优

若 = 0,那么就是最小值了

1.二分

//19100K 1235MS
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=1005;
const double eps=1e-4,INF=1e8; int n,x[N],y[N],z[N],cost[N][N];
double dis[N][N],e[N][N],d[N];
bool vis[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline double Calc(int i,int j) {return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.0*(y[i]-y[j])*(y[i]-y[j]));}
bool Check(double x)
{
for(int i=1; i<=n; ++i)
for(int j=i+1; j<=n; ++j)
e[j][i]=e[i][j]=1.0*cost[i][j]-x*dis[i][j];
double res=0;//Prim
memset(vis,0,sizeof vis);
for(int i=2; i<=n; ++i) d[i]=e[1][i];
d[0]=INF, vis[1]=1;
for(int now,i=1; i<n; ++i)
{
now=0;
for(int j=2; j<=n; ++j)
if(!vis[j] && d[j]<d[now]) now=j;
vis[now]=1, res+=d[now];
for(int j=2; j<=n; ++j)
if(!vis[j] && d[j]>e[now][j])
d[j]=e[now][j];
}
return res<=0;
} int main()
{
while(n=read(),n)
{
for(int i=1; i<=n; ++i) x[i]=read(),y[i]=read(),z[i]=read();
for(int i=1; i<n; ++i)
for(int j=i+1; j<=n; ++j)
dis[i][j]=Calc(i,j),cost[i][j]=std::abs(z[i]-z[j]);
double l=0.0,r=101.0,mid;//r=多少啊。。
while(r-l>=eps)
{
if(Check(mid=(l+r)/2.0)) r=mid;
else l=mid;
}
printf("%.3f\n",l);//POJ不能用%lf! 惊了 刚知道
}
return 0;
}

2.Dinkelbach迭代

/*
20076K 297MS
并不明白原理 先将就用
*/
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=1005;
const double eps=1e-4,INF=1e8; int n,x[N],y[N],z[N],cost[N][N],pre[N];
double dis[N][N],e[N][N],d[N];
bool vis[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline double Calc(int i,int j) {return sqrt(1.0*(x[i]-x[j])*(x[i]-x[j])+1.0*(y[i]-y[j])*(y[i]-y[j]));}
double Check(double x)
{
for(int i=1; i<=n; ++i)
for(int j=i+1; j<=n; ++j)
e[j][i]=e[i][j]=1.0*cost[i][j]-x*dis[i][j];
double Dis=0,Cost=0;//Prim
memset(vis,0,sizeof vis);
for(int i=2; i<=n; ++i) d[i]=e[1][i],pre[i]=1;
d[0]=INF, vis[1]=1;
for(int now,i=1; i<n; ++i)
{
now=0;
for(int j=2; j<=n; ++j)
if(!vis[j] && d[j]<d[now]) now=j;
vis[now]=1, Dis+=dis[pre[now]][now], Cost+=cost[pre[now]][now];
for(int j=2; j<=n; ++j)
if(!vis[j] && d[j]>e[now][j])
d[j]=e[now][j], pre[j]=now;
}
return Cost/Dis;
} int main()
{
while(n=read(),n)
{
for(int i=1; i<=n; ++i) x[i]=read(),y[i]=read(),z[i]=read();
for(int i=1; i<n; ++i)
for(int j=i+1; j<=n; ++j)
dis[j][i]=dis[i][j]=Calc(i,j), cost[j][i]=cost[i][j]=std::abs(z[i]-z[j]);
double x=0,y;
while(1)
{
y=Check(x);
if(fabs(x-y)<eps) break;
x=y;
}
printf("%.3f\n",x);
}
return 0;
}

POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)的更多相关文章

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

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

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

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

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

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

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

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

  5. Desert King(最优比率生成树)

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

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

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

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

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

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

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

  9. poj 2728 最优比例生成树(01分数规划)模板

    /* 迭代法 :204Ms */ #include<stdio.h> #include<string.h> #include<math.h> #define N 1 ...

随机推荐

  1. u盘的一些理解

    U盘是由主控板+FLASH+外壳组成的,当主控板焊接上空白FLASH后插入电脑,因为没有相应的数据,  量产工具 电脑只能识别到主控板,而无法识别到FLASH,所以这时候电脑上显示出U盘盘符,但是双击 ...

  2. jython获取was5.1的jvm监控参数

    perfName = AdminControl.completeObjectName ('type=Perf,process=server1,node=TSC,cell=TSC,*') perfONa ...

  3. yum install oracle-validated

    背景 当时心血来潮要在linux搞oracle,可一顿折腾,大约两个周时间,主要是各种环境的检测麻烦,在redhat上操作也不如centos有利. 命令 yum install oracle-vali ...

  4. uboot 传递的参数 mtdparts

    启动uboot后,在重新烧写程序之前,查看传递给内核的参数时(命令为: printenv),看到如下内容: bootargs=console=ttyS0,115200 mtdparts=spi0.0: ...

  5. 03-Bootstrap学习

    一.Bootstrap的介绍 凡是使用过Bootstrap的开发者,都不在乎做这么两件事情:复制and粘贴.哈哈~,是的使用Bootstrap非常简单,但是在复制粘贴之前,需要先对Bootstrap的 ...

  6. 【转载】如何让图片按比例响应式缩放、并自动裁剪的css技巧

    原文: http://blog.csdn.net/oulihong123/article/details/54601030 响应式网站.移动端页面在DIV CSS布局中对于图片列表或图片排版时, 如果 ...

  7. js闭包之应用场景

    闭包的解释 当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包 在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义 ...

  8. Deep Learning系统实训之三:卷积神经网络

    边界填充(padding):卷积过程中,越靠近图片中间位置的像素点越容易被卷积计算多次,越靠近边缘的像素点被卷积计算的次数越少,填充就是为了使原来边缘像素点的位置变得相对靠近中部,而我们又不想让填充的 ...

  9. Redis、RabbitMQ、Memcached

    知识目录: Memcached Redis RabbitMQ Memcached 回到顶部 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中 ...

  10. python 全栈开发,Day132(玩具管理页面,控制玩具通讯录,基于请求的好友关系建立)

    先下载github代码,下面的操作,都是基于这个版本来的! https://github.com/987334176/Intelligent_toy/archive/v1.5.zip 注意:由于涉及到 ...