POJ 2728 Desert King(最优比率生成树, 01分数规划)
题意:
给定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分数规划)的更多相关文章
- POJ 2728 Desert King 最优比率生成树
Desert King Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 20978 Accepted: 5898 [Des ...
- POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)
题目链接 \(Description\) 将n个村庄连成一棵树,村之间的距离为两村的欧几里得距离,村之间的花费为海拔z的差,求花费和与长度和的最小比值 \(Solution\) 二分,假设mid为可行 ...
- POJ 2728 Desert King(最优比率生成树 01分数规划)
http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简 ...
- Desert King (poj 2728 最优比率生成树 0-1分数规划)
Language: Default Desert King Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 22113 A ...
- POJ 2728 Desert King (最优比率树)
题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目 ...
- POJ 2728 Desert King (最优比例生成树)
POJ2728 无向图中对每条边i 有两个权值wi 和vi 求一个生成树使得 (w1+w2+...wn-1)/(v1+v2+...+vn-1)最小. 采用二分答案mid的思想. 将边的权值改为 wi- ...
- Desert King(最优比率生成树)
Desert King Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 22717 Accepted: 6374 Desc ...
- POJ2728 Desert King —— 最优比率生成树 二分法
题目链接:http://poj.org/problem?id=2728 Desert King Time Limit: 3000MS Memory Limit: 65536K Total Subm ...
- 【POJ2728】Desert King 最优比率生成树
题目大意:给定一个 N 个点的无向完全图,边有两个不同性质的边权,求该无向图的一棵最优比例生成树,使得性质为 A 的边权和比性质为 B 的边权和最小. 题解:要求的答案可以看成是 0-1 分数规划问题 ...
随机推荐
- FZu Problem 2236 第十四个目标 (线段树 + dp)
题目链接: FZu Problem 2236 第十四个目标 题目描述: 给出一个n个数的序列,问这个序列内严格递增序列有多少个?不要求连续 解题思路: 又遇到了用线段树来优化dp的题目,线段树节点里 ...
- 题解报告:poj 1985 Cow Marathon(求树的直径)
Description After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to ge ...
- Java图解
java虚拟机 JVM运行过程: java开发工具包 java入门图解1 java入门图解2 java入门图解3 java入门图解4
- H5页面快速搭建之高级字体应用实践
原文出处: 淘宝前端团队(FED)- 龙驭 背景 最近在开发一个 H5 活动页快速搭建平台,可以通过拖拽编辑图片,文字等元素组件,快速搭建出一个移动端的活动页面,基本交互和成品效果类似 PPT 软件. ...
- AJPFX:求两个城市之间的距离
键盘录入多个城市: 城市1,城市2,城市3 以 ### 结束输出然后再键盘录入各个城市之间的距离: 格式如下:0,12,4512,0,2245,22,0### 然后按照输入的两个城市,求得两个城市 ...
- poj2184 Cow Exhibition
思路: dp+滚动数组. 类似01背包. 实现: #include <iostream> #include <cstdio> #include <algorithm> ...
- JS进阶-特殊形式的函数-内部私有函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Android虚拟机电池状态设置
问题描述: 安装SDK后使用AVD配合APPIUM进行测试,此时虚拟机的电池状态为0%充电中:部分APP会对手机电池状态有要求,不符合要求时,无法安装或打开. 解决思路: 1.Android系统设置( ...
- win应用只允许单个实例运行,并将已运行实例窗口置顶
关键词:windows,c++,桌面应用,单个实例,窗口置顶 目标:1.判断本程序是否已有一个实例在运行.2.若有,则激活已在运行的实例(将其窗口置顶),并退出当前运行. 1.使用semaphore来 ...
- Javaweb学习笔记7—JDBC技术
今天来讲javaweb的第7阶段学习. JDBC技术,关于JDBC本篇博客只介绍了它的一部分,后面博客会更加深入探讨. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps:我的思维是用的 ...