poj2728(最小比率生成树)
poj2728
题意
给出 n 个点的坐标和它的高度,求一颗生成树使得树上所连边的两点高度差之和除以距离之和最小。
分析
01分数规划+最小生成树。
对于所有的边,在求最小生成树过程中有选或不选的问题,
首先根据01分数规划,我们要使 $ l = \frac{\sum_{i=1}^{n} height[i] * exist[i]}{\sum_{i=1}^{n} dis[i] * exist[i]}$ (exist[i]表示是否有这条边)最小,
设 \(F(l) = {\sum height[i]*exist[i]}-l*{\sum dis[i]*exist[i]}\) ,我们要使 \(l\) 尽可能的小, \(F(l)\) 随 \(l\) 减小而递增,如果 \(F(l) < 0\) ,
\(\frac{\sum_{i=1}^{n} height[i] * exist[i]}{\sum_{i=1}^{n} dis[i] * exist[i]} < l\) ,即存在更优的 \(l\) ,当 \(F(l) = 0\) 时,即为最终最终答案 \(l\) 。
设 \(D(l) = height[i] - dis[i] * l\) ,把它作为边,求最小生成树,那么求得值 \(F(l)\) 一定是尽可能小的,越有可能出现更优的 \(l\) 。
本题适于采用迭代法,因为在求最小生成树的过程中,就可以计算出更优的 \(l\) 值。
code(二分法)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 10;
const double INF = 1e15;
int n;
double dist(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
struct node {
double x, y, h;
}a[MAXN];
double height[MAXN][MAXN];
double map[MAXN][MAXN];
double dis[MAXN];
int vis[MAXN];
double prime(double rate) {
double sum = 0;
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) {
dis[i] = INF;
}
dis[1] = 0;
for(int i = 0; i < n; i++) {
double MIN = INF;
int k;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] < MIN) MIN = dis[k = j];
}
vis[k] = 1;
sum += MIN;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] > height[k][j] - rate * map[k][j]) {
dis[j] = height[k][j] - rate * map[k][j];
}
}
}
return sum;
}
void solve() {
double l = 0, r = 1e5, mid = 0;
while(r - l > 1e-6) {
mid = (l + r) / 2;
if(prime(mid) < 0) r = mid;
else l = mid;
}
printf("%.3f\n", mid);
}
int main() {
while(cin >> n && n) {
for(int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y >> a[i].h;
for(int j = 1; j <= i; j++) {
map[i][j] = map[j][i] = dist(a[i].x, a[i].y, a[j].x, a[j].y);
height[i][j] = height[j][i] = abs(a[i].h - a[j].h);
}
}
solve();
}
return 0;
}
code(迭代法)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 10;
const double INF = 1e15;
int n;
double dist(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
struct node {
double x, y, h;
}a[MAXN];
double height[MAXN][MAXN];
double map[MAXN][MAXN];
double dis[MAXN];
int vis[MAXN], pre[MAXN];
double prime(double rate) {
double sum = 0;
double sumh = 0, sumd = 0;
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) {
dis[i] = INF;
pre[i] = 0;
}
dis[1] = 0;
for(int i = 0; i < n; i++) {
double MIN = INF;
int k;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] < MIN) {
MIN = dis[k = j];
}
}
vis[k] = 1;
sum += MIN;
sumd += map[pre[k]][k];
sumh += height[pre[k]][k];
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] > height[k][j] - rate * map[k][j]) {
dis[j] = height[k][j] - rate * map[k][j];
pre[j] = k;
}
}
}
return sumh / sumd;
}
void solve() {
double k = 0, tmp;
while(1) {
tmp = prime(k);
if(fabs(tmp - k) < 1e-6) break;
else k = tmp;
}
printf("%.3f\n", k);
}
int main() {
while(cin >> n && n) {
for(int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y >> a[i].h;
for(int j = 1; j <= i; j++) {
map[i][j] = map[j][i] = dist(a[i].x, a[i].y, a[j].x, a[j].y);
height[i][j] = height[j][i] = abs(a[i].h - a[j].h);
}
}
solve();
}
return 0;
}
poj2728(最小比率生成树)的更多相关文章
- POJ2728 最小比率生成树/0-1分数规划/二分/迭代(迭代不会)
用01分数规划 + prime + 二分 竟然2950MS惊险的过了QAQ 前提是在TLE了好几次下过的 = = 题目意思:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一 ...
- poj2728 最小比率生成树——01分数规划
题目大意: 有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水, 只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差, 现在要求方案使得费用与距离的比值最小,很显然 ...
- poj 2728 Desert King(最小比率生成树,迭代法)
引用别人的解释: 题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可, 建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差 现在要求 ...
- Desert King 最小比率生成树 (好题)
Description David the Great has just become the king of a desert country. To win the respect of his ...
- 最小比率树 poj2728
以下内容均为转载 http://www.cnblogs.com/ftae/p/6947497.html poj2728(最小比率生成树) poj2728 题意 给出 n 个点的坐标和它的高度,求一 ...
- POJ2728 Desert King 【最优比率生成树】
POJ2728 Desert King Description David the Great has just become the king of a desert country. To win ...
- 最优比率生成树 poj2728
Desert King Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 28407 Accepted: 7863 Desc ...
- 【最优比率生成树】poj2728 Desert King
最优比率生成树教程见http://blog.csdn.net/sdj222555/article/details/7490797 个人觉得很明白易懂,但他写的代码略囧. 模板题,但是必须Prim,不能 ...
- [POJ2728] Desert King 解题报告(最优比率生成树)
题目描述: David the Great has just become the king of a desert country. To win the respect of his people ...
随机推荐
- Java EE - Servlet 小结
Table of Contents 前言 Servlet 的生命周期 Servlet 的初始化 ServletContext & ServletConfig 请求的处理 HttpServlet ...
- FileZilla修改文件大小格式
之前使用FileZilla觉得很奇怪,文件大小显示为字节格式,很不习惯. 最近发现是在这里修改. 菜单“编辑”下选择设置,选择选项“文件大小格式”,在右边选择为:“使用SI式二进制前缀.(如 1 KB ...
- hadoop2.5.2学习及实践笔记(六)—— Hadoop文件系统及其java接口
文件系统概述 org.apache.hadoop.fs.FileSystem是hadoop的抽象文件系统,为不同的数据访问提供了统一的接口,并提供了大量具体文件系统的实现,满足hadoop上各种数据访 ...
- Vue.js入门(一)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <meta htt ...
- HTML5 localStorage与document.domain设置问题
localStorage的写入和读取,不能跨子域,否则在一些移动端浏览器上,会出现读取不到的情况. 最近开发一个移动端的播放记录功能,在pc端和android版的chrome测试很顺利通过了,但后来进 ...
- ubuntu服务器环境配置参考
一.基本的Linux系统命令: ls 查看当前目录下的文件及文件夹 cd /var/www/html 转换目录到/var/www/html cd abc/ddd/ 转换目录到当前目录下的abc文件夹下 ...
- http登陆时的密码加密
系统设计登陆页面的时候,需要谨慎.因为登陆数据是在网络上进行传输,很可能中途被拦截. 最好的登陆是使用https,这样网络传输是安全的.google,baidu,alibaba都使用https的方式. ...
- Java面试题之类加载器有哪些?什么是双亲委派模型
类加载器有哪些: 1.启动类加载器(Bootstrap ClassLoader):这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或被-Xbootclasspath参数所指 ...
- 蓝牙HC-05与HC-06对比指令集
高电平->AT命令响应工作状态 低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06虽然可以做主机也可以做从机,但是不能切 ...
- C++封装随笔
1接口的封装和设计思想入门 接口的封装和设计思想入门 第一套api函数 #ifndef _CLT_SOCKET_H__ #define _CLT_SOCKET_H__ //客户端初始化环境 int c ...