题目链接

\(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.二分

  1. //19100K 1235MS
  2. #include <cmath>
  3. #include <cstdio>
  4. #include <cctype>
  5. #include <cstring>
  6. #include <algorithm>
  7. #define gc() getchar()
  8. const int N=1005;
  9. const double eps=1e-4,INF=1e8;
  10. int n,x[N],y[N],z[N],cost[N][N];
  11. double dis[N][N],e[N][N],d[N];
  12. bool vis[N];
  13. inline int read()
  14. {
  15. int now=0;register char c=gc();
  16. for(;!isdigit(c);c=gc());
  17. for(;isdigit(c);now=now*10+c-'0',c=gc());
  18. return now;
  19. }
  20. 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]));}
  21. bool Check(double x)
  22. {
  23. for(int i=1; i<=n; ++i)
  24. for(int j=i+1; j<=n; ++j)
  25. e[j][i]=e[i][j]=1.0*cost[i][j]-x*dis[i][j];
  26. double res=0;//Prim
  27. memset(vis,0,sizeof vis);
  28. for(int i=2; i<=n; ++i) d[i]=e[1][i];
  29. d[0]=INF, vis[1]=1;
  30. for(int now,i=1; i<n; ++i)
  31. {
  32. now=0;
  33. for(int j=2; j<=n; ++j)
  34. if(!vis[j] && d[j]<d[now]) now=j;
  35. vis[now]=1, res+=d[now];
  36. for(int j=2; j<=n; ++j)
  37. if(!vis[j] && d[j]>e[now][j])
  38. d[j]=e[now][j];
  39. }
  40. return res<=0;
  41. }
  42. int main()
  43. {
  44. while(n=read(),n)
  45. {
  46. for(int i=1; i<=n; ++i) x[i]=read(),y[i]=read(),z[i]=read();
  47. for(int i=1; i<n; ++i)
  48. for(int j=i+1; j<=n; ++j)
  49. dis[i][j]=Calc(i,j),cost[i][j]=std::abs(z[i]-z[j]);
  50. double l=0.0,r=101.0,mid;//r=多少啊。。
  51. while(r-l>=eps)
  52. {
  53. if(Check(mid=(l+r)/2.0)) r=mid;
  54. else l=mid;
  55. }
  56. printf("%.3f\n",l);//POJ不能用%lf! 惊了 刚知道
  57. }
  58. return 0;
  59. }

2.Dinkelbach迭代

  1. /*
  2. 20076K 297MS
  3. 并不明白原理 先将就用
  4. */
  5. #include <cmath>
  6. #include <cstdio>
  7. #include <cctype>
  8. #include <cstring>
  9. #include <algorithm>
  10. #define gc() getchar()
  11. const int N=1005;
  12. const double eps=1e-4,INF=1e8;
  13. int n,x[N],y[N],z[N],cost[N][N],pre[N];
  14. double dis[N][N],e[N][N],d[N];
  15. bool vis[N];
  16. inline int read()
  17. {
  18. int now=0;register char c=gc();
  19. for(;!isdigit(c);c=gc());
  20. for(;isdigit(c);now=now*10+c-'0',c=gc());
  21. return now;
  22. }
  23. 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]));}
  24. double Check(double x)
  25. {
  26. for(int i=1; i<=n; ++i)
  27. for(int j=i+1; j<=n; ++j)
  28. e[j][i]=e[i][j]=1.0*cost[i][j]-x*dis[i][j];
  29. double Dis=0,Cost=0;//Prim
  30. memset(vis,0,sizeof vis);
  31. for(int i=2; i<=n; ++i) d[i]=e[1][i],pre[i]=1;
  32. d[0]=INF, vis[1]=1;
  33. for(int now,i=1; i<n; ++i)
  34. {
  35. now=0;
  36. for(int j=2; j<=n; ++j)
  37. if(!vis[j] && d[j]<d[now]) now=j;
  38. vis[now]=1, Dis+=dis[pre[now]][now], Cost+=cost[pre[now]][now];
  39. for(int j=2; j<=n; ++j)
  40. if(!vis[j] && d[j]>e[now][j])
  41. d[j]=e[now][j], pre[j]=now;
  42. }
  43. return Cost/Dis;
  44. }
  45. int main()
  46. {
  47. while(n=read(),n)
  48. {
  49. for(int i=1; i<=n; ++i) x[i]=read(),y[i]=read(),z[i]=read();
  50. for(int i=1; i<n; ++i)
  51. for(int j=i+1; j<=n; ++j)
  52. dis[j][i]=dis[i][j]=Calc(i,j), cost[j][i]=cost[i][j]=std::abs(z[i]-z[j]);
  53. double x=0,y;
  54. while(1)
  55. {
  56. y=Check(x);
  57. if(fabs(x-y)<eps) break;
  58. x=y;
  59. }
  60. printf("%.3f\n",x);
  61. }
  62. return 0;
  63. }

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. WPF版公司的自动签到程序

    1.外包公司要求早上签到,就写了一个自动打卡程序. 2.一直都想写这个程序,可是一直没有思路,知道有个软件公司找我做自动答题程序,于是自动打卡程序才应运而生.未来可以将自动答题程序开源工大家查看. 3 ...

  2. 转载CSDN博客步骤

    在参考“如何快速转载CSDN中的博客”后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考博客原址:http: ...

  3. 转载:abstract的方法是否可同时是static,是否可同时是native,是否可同时是synchronized?

    原文:http://blog.csdn.net/fhm727/article/details/5222965 1.abstract与static (what) abstract:用来声明抽象方法,抽象 ...

  4. convertToNodeSpace和convertToWorldSpace ---实际应用

    游戏中经常会用到一些变换: 游戏中武器和角色在一个layer上,为了效率,会考虑将bullet, effect和 PhysicsParticle分别放到不用的层上,对应的层上使用batchnode来提 ...

  5. WM8960音频播放

    第一节 音频播放原理首先需要申明一下,本章的代码来自网络,参考了亚嵌教育李明老师(论坛ID:limingth)的帖子: http://www.arm9home.net/read.php?tid=205 ...

  6. Python-JS (JS介绍~JS的基础数据类型)

    目录一.JS语言介绍: 1.JS概念 2.JS组成 二.JS的三种存在位置(引入方式): 1.行间式: 2.内联式: 3.外联式: 三.JS出现的具体位置: 四.JS语法规范 五.JS中变量的定义 E ...

  7. 轻量架构ShuffleNet V2:从理论复杂度到实用设计准则

    转自:机器之心 近日,旷视科技提出针对移动端深度学习的第二代卷积神经网络 ShuffleNet V2.研究者指出过去在网络架构设计上仅注重间接指标 FLOPs 的不足,并提出两个基本原则和四项准则来指 ...

  8. log4j2 使用详解

    转载自 Blog of 天外的星星: http://www.cnblogs.com/leo-lsw/p/log4j2tutorial.html Log4j 2的好处就不和大家说了,如果你搜了2,说明你 ...

  9. cf1104d二分+数学

    #include<bits/stdc++.h> using namespace std; bool ask(int x,int y){ printf("? %d %d\n&quo ...

  10. poj3468

    #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define ...