题意:给n个点,可以将每个点的x,y的欧几里得距离(就是坐标系里两点距离公式)看作距离,z的差值即为费用差,求的是所有最小生成树中的min(边费用和/边距离和)。

思路:其实挑战P143有类似的列题,用的是二分枚举答案的方法,只不过不是树。这一题仅仅需要将题给图找出最小生成树,然后同样枚举即可。

虽然网上有许多高级的名词什么最优比率xxx之类的。。以及迭代的方法,不过我认为用二分也很好,易于想到也可以加深理解。

 #include <iostream>

 #include <string>

 #include <cstdio>

 #include <cstring>

 #include <cstdlib>

 #include <algorithm>

 #include <cmath>

 #define MAXN 1005

 #define INF 1000000000

 #define eps 1e-7

 using namespace std;

 int n;

 double Edge[MAXN][MAXN], lowcost[MAXN];

 int nearvex[MAXN];

 struct Point

 {

     int x, y, z;

 }p[MAXN];

 double cal(int a, int b)

 {

     return sqrt(1.0 * (p[a].x - p[b].x) * (p[a].x - p[b].x) + 1.0 * (p[a].y - p[b].y) * (p[a].y - p[b].y));

 }

 double prim(int src, double l)

 {

     double cost = , len = ;

     double sum = ;

     for(int i = ; i <= n; i++)

     {

         nearvex[i] = src;

         lowcost[i] = abs(p[src].z - p[i].z) - Edge[src][i] * l;

     }

     nearvex[src] = -;

     for(int i = ; i < n; i++)

     {

         double mi = INF;

         int v = -;

         for(int j = ; j <= n; j++)

             if(nearvex[j] != - && lowcost[j] < mi)

             {

                 v = j;

                 mi = lowcost[j];

             }

         if(v != -)

         {

             cost += abs(p[nearvex[v]].z - p[v].z);

             len += Edge[nearvex[v]][v];

             nearvex[v] = -;

             sum += lowcost[v];

             for(int j = ; j <= n; j++)

             {

                 double tmp = abs(p[v].z - p[j].z) - Edge[v][j] * l;

                 if(nearvex[j] != - && tmp < lowcost[j])

                 {

                     lowcost[j] = tmp;

                     nearvex[j] = v;

                 }

             }

         }

     }

     return sum;

 }

 int main()

 {

     while(scanf("%d", &n) != EOF && n)

     {

         for(int i = ; i <= n; i++)

             scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z);

         for(int i = ; i <= n; i++)

             for(int j = ; j <= n; j++)

                 Edge[i][j] = cal(i, j);

         double low = , high = 10.0;             //其实二分20多次已经很足够了

         double l = 0.0, r = 100.0, mid;

         while(r - l > eps)

         {

             mid = (l + r) / ;

             if(prim(, mid) >= ) l = mid;

             else r = mid;

         }

         printf("%.3f\n", r);

     }

     return ;

 }

最新文章

  1. 【bzoj4514】 Sdoi2016—数字配对
  2. Microsoft Azure Project Oxford 体验
  3. MYSQL操作数据表中的记录
  4. MyEclipse简单设置
  5. Android 通过ViewFlipper实现广告轮播功能并可以通过手势滑动进行广告切换
  6. JSF教程(10)——生命周期之Update Model Values Phase
  7. centos搭建本地库
  8. Cocos2d-x中背景音乐播放暂停与继续
  9. Trie,HDU1875world puzzle
  10. bzoj3878
  11. Http 状态码详解
  12. hadoop输出统计
  13. tinkphp URL重写,支持伪静态
  14. elk 分布式数据同步
  15. css三种布局方式
  16. PHP----SAPI
  17. 报错:No identifier specified for entity: main.java.com.sy.entity.User的解决办法
  18. GoLang simple-project-demo-03
  19. 【开源GPS追踪】 之 为何费力不讨好
  20. idea基于hibernate生成的Entitle对象,会忽略外键属性

热门文章

  1. Java之线程通信的方法
  2. OpenCV学习与应用
  3. typescript-学习使用ts-1
  4. python获取当前的日期和时间
  5. Spring集成MyBatis配置文件
  6. remove_if 的效率测试
  7. idea新建maven项目后生成web.xml方法和添加到tomcat方法
  8. D - Project Presentation(DFS序+倍增LCA)
  9. aws基础架构学习笔记
  10. day04-函数,装饰器初成