题意:

给定n个村子的坐标(x,y)和高度z, 求出修n-1条路连通所有村子, 并且让 修路花费/修路长度 最少的值

两个村子修一条路, 修路花费 = abs(高度差), 修路长度 = 欧氏距离

分析:

01分数划分的题目, 构造出 d[i] = 修路花费 - L * 修路长度, 这个L值我们可以二分(这道题看数据范围的话二分上限其实挺大的, 但其实上限取到100就可以过), 也可以用Dinkelbach迭代出来。

二分(1422ms)

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <cmath>
#define rep(i,a,b) for(int i = a; i < b;i++)
#define _rep(i,a,b) for(int i = a; i <= b;i++)
using namespace std;
const int maxn = + ;
const double inf = 1e9 + ;
const double eps = 1e-;
int n; double G[maxn][maxn];
double x[maxn], y[maxn], z[maxn]; inline double p2p_dis(double x1, double y1, double x2, double y2){
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
double prim(double L){
double tree_dis = ;
double dis[maxn];
int vis[maxn];
fill(dis, dis + maxn, inf);
memset(vis, ,sizeof(vis)); dis[] = ;
vis[] = ; for(int i = ; i < n; i++) dis[i] = abs(z[] - z[i]) - L * G[][i]; for(int times = ; times < n - ; times++){
int picked = -;
double min_dis = inf;
for(int i = ; i < n; i++){
if(!vis[i] && dis[i] < min_dis){
min_dis = dis[i];
picked = i;
}
}
tree_dis += min_dis;
vis[picked] = ;
for(int i = ; i < n; i++)
if(!vis[i])
dis[i] = min(dis[i] , abs(z[picked] - z[i]) - L * G[picked][i]) ;
}
return tree_dis;
} int main(){
// freopen("1.txt","r", stdin);
while(cin >> n && n){
rep(i,,n) cin >> x[i] >> y[i] >> z[i];
rep(i,,n) rep(j,i+,n) G[i][j] = G[j][i] = p2p_dis(x[i],y[i],x[j],y[j]);
double l = , r = ;
while(abs(r - l) > eps){
double mid = (l + r) / ;
// printf("%.3f\n", mid);
if(prim(mid) >= ){
l = mid;
}else{
r = mid;
}
}
printf("%.3f\n", l);
}
return ;
}

Dinkelbach(204ms)

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstring>
#include <cmath>
#define rep(i,a,b) for(int i = a; i < b;i++)
#define _rep(i,a,b) for(int i = a; i <= b;i++)
using namespace std;
const int maxn = + ;
const double inf = 1e9 + ;
const double eps = 1e-;
int n; double G[maxn][maxn];
double x[maxn], y[maxn], z[maxn]; inline double p2p_dis(double x1, double y1, double x2, double y2){
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
double prim(double L){
double ele = , deno = ; //分子分母
double dis[maxn];
int near[maxn]; //开一个数组记录每次选中是哪一条边 int vis[maxn];
fill(dis, dis + maxn, inf);
memset(vis, ,sizeof(vis));
memset(near, -, sizeof(near));
dis[] = ;
vis[] = ; for(int i = ; i < n; i++) dis[i] = abs(z[] - z[i]) - L * G[][i], near[i] = ; //每个点都是由0点更新的, 所以near都是0 for(int times = ; times < n - ; times++){
int picked = -;
double min_dis = inf;
for(int i = ; i < n; i++){
if(!vis[i] && dis[i] < min_dis){
min_dis = dis[i];
picked = i;
}
}
ele += abs(z[near[picked]] - z[picked]);//分子是选的路程
deno += G[near[picked]][picked]; //分母是真实的花费
vis[picked] = ;
for(int i = ; i < n; i++)
if(!vis[i] && dis[i] > abs(z[picked] - z[i]) - L * G[picked][i]){
dis[i] = abs(z[picked] - z[i]) - L * G[picked][i];
near[i] = picked;//如果通过picked点更新dis,那么该位置near就是picked
} } return ele/deno; //注意返回的跟二分不一样, 应该返回当前L下真正题目的所求
} int main(){
// freopen("1.txt","r", stdin);
while(cin >> n && n){
rep(i,,n) cin >> x[i] >> y[i] >> z[i];
rep(i,,n) rep(j,i+,n) G[i][j] = G[j][i] = p2p_dis(x[i],y[i],x[j],y[j]);
double L, ans = ;
while(){
L = ans;
ans = prim(L); //这是一个真实值, 不是含L的变式
if(abs(ans - L)< eps) break;
}
printf("%.3f\n", ans);
}
return ;
}

POJ 2728 Desert King(最优比率生成树, 01分数规划)的更多相关文章

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

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

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

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

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

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

  4. Desert King (poj 2728 最优比率生成树 0-1分数规划)

    Language: Default Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 22113   A ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. the little schemer 笔记(8)

    第八章 lambda the ultimate 还记得我们第五章末的rember和insertL吗 我们用equal?替换了eq? 你能用你eq?或者equal?写一个函数rember-f吗 还不能, ...

  2. python之请求报文对比(假定最多二维字典)

    两段请求报文,判断不一样的key和value,只判断d2里和d1不同的值,和全部不同的key ok_req={ "version": "9.0.0", &quo ...

  3. 总结 - 常见的JavaScript兼容性问题

    添加事件的方法 (元素, 绑定的事件类型, 事件触发的方法) addHandler: function (element, type, handler) { if (element.addEventL ...

  4. MySQL FailOver(官方自带,free)

    为什么 传统复制和GTIDs切换的缺点 当replication故障出现之后,最头疼是replication架构的调整 一旦master down了,就需要配置某一台slave作为master sla ...

  5. Android开发-浅谈架构(一)

    写在前面的话 嗯 聊聊架构. 这段时间一直在维护旧项目. 包括自己之前写的新项目 越来越发现 一个架构清晰的项目往往让人赏心悦目.不至于在一个bug丢过来之后手足无措.包括以后别人接收自己的项目 能很 ...

  6. ICEcoder显示汉字出现乱码的处理

    在网上看到icecoder这个小东西,是一个基于web的编辑器,很不错.唯一的缺点是打开的文件中汉字会变成乱码. 经查看源代码,在lib/file-control.php中,第89行是: echo ' ...

  7. 1   开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你。   本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的原则已经被许多现有的JDBC应用程序编译运行并验证过。 这些指导原则包括:    正确的使用数据库MetaData方法    只获取需要的数据    选用最佳性能的功能    管理连

    1 开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你. 本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的 ...

  8. SQL——将两列合并成一列

    将两列合并连接成一列,需要注意的是列的格式必须是NVARCHAR或者VARCHAR类型 ), call_uuid, ) +','+agent_code '   PerDate 1 ,980408102 ...

  9. 纯手写的css3正方体旋转效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. SQLite -创建数据库

    SQLite -创建数据库 SQLite sqlite3命令用于创建新的SQLite数据库.你不需要有任何特权来创建一个数据库. 语法: sqlite3命令的基本语法如下: $sqlite3 Data ...