zoukankan      html  css  js  c++  java
  • POJ2728——最优比例生成树

    题目链接:https://vjudge.net/problem/POJ-2728

    题目意思:给你n个村庄的坐标和每个村庄的海拔。建设管道需要花费(为两村庄高度差)。现在求 总花费/总距离(各条线路的距离)的最小值。

    思路:https://www.jianshu.com/p/d40a740a527e

    入门级别,0/1规划,最优入门题。用链式前向星、Dis数组放外面会T成SB

    二分法:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<iomanip>
     5 #include<algorithm>
     6 #include<string.h>
     7 #define eqs 1e-6;
     8 using namespace std;
     9 const int MAXN = 1010;
    10 const int INF = 999999;
    11 double Graph[MAXN][MAXN];
    12 struct P{
    13     double x,y,z;
    14 }Cy[MAXN];
    15 int N;
    16 double distance(double x1,double y1,double x2,double y2){
    17     double ret=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    18     return sqrt(ret);
    19 }
    20 void UpdateMap(double l){
    21     for(int i = 1;i <= N;i ++){
    22         for(int j = 1;j <= N;j ++){
    23             Graph[i][j] = fabs(Cy[i].z - Cy[j].z) - l * distance(Cy[i].x,Cy[i].y,Cy[j].x,Cy[j].y);
    24         }
    25     }
    26 }
    27 double dis[MAXN];
    28 double prim(){
    29     double minn;
    30     double sum = 0;
    31     bool vis[MAXN];
    32     int now;
    33     memset(vis,0,sizeof(vis));
    34     for(int i = 1;i <= N;i ++){
    35         dis[i] = Graph[1][i];
    36     }
    37     vis[1] = 1;
    38     for(int i = 1;i <= N;i ++){
    39         minn = INF;
    40         for(int j = 1;j <= N;j++){
    41             if(!vis[j]){
    42                 if(dis[j] < minn){
    43                     now = j;
    44                     minn = dis[j];
    45                 }
    46             }
    47         }
    48         if(minn == INF) break;
    49         sum += minn;
    50         vis[now] = 1;//cout<<"i = "<<i<<endl;
    51         for(int j = 1;j <= N;j ++){
    52             if(!vis[j] && dis[j] >= Graph[now][j])
    53                 dis[j] = Graph[now][j];
    54         }
    55     }
    56     return sum;
    57 }
    58 int main(){
    59     while(cin>>N,N){
    60         for(int i = 1;i <= N;i ++){
    61             cin>>Cy[i].x>>Cy[i].y>>Cy[i].z;
    62         }
    63         double high = 100.0;
    64         double low = 0.0 , pre = 0.0;
    65         double mid,ans;
    66         while(low <= high){
    67             mid = (high + low)/2;
    68             UpdateMap(mid);
    69             ans = prim();
    70             if(fabs(pre - ans) <= 0.0005) break;
    71             if(ans > 0.0005) low = mid;
    72             else high = mid;
    73         }
    74 //        cout<<fixed<<setprecision(3)<<mid<<endl;
    75         printf("%.3lf
    ",mid);
    76     }
    77     return 0;
    78 }

     迭代法:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<string.h>
     5 #include<algorithm>
     6 #include<iomanip>
     7 using namespace std;
     8 const int N = 1010;
     9 const int INF = 999999;
    10 struct P{
    11     double x,y,z;
    12 }num[N];
    13 int n;
    14 double mp[N][N],cost[N][N],len[N][N];
    15 double cal(double x1,double y1,double x2,double y2){
    16     return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
    17 }
    18 double dis[N];
    19 bool vis[N];
    20 int now , pre[N];
    21 double prim(){
    22     double sum = 0;
    23     double sumlen = 0,sumcost = 0;
    24     for(int i = 1;i <= n;i ++){
    25         dis[i] = mp[1][i];
    26         vis[i] = false;
    27         pre[i] = 1;
    28     }
    29     vis[1] = true;
    30     for(int i = 1;i <= n;i ++){
    31         double minn = INF;
    32         for(int j = 1;j <= n ;j ++){
    33             if(!vis[j]){
    34                 if(dis[j] < minn){
    35                     minn = dis[j];
    36                     now = j;
    37                 }
    38             }
    39         }
    40         if(minn == (double)INF) break;
    41         sumlen += len[pre[now]][now];
    42         sumcost += cost[pre[now]][now];
    43 //        cout<<"now = "<<now<<endl;
    44         vis[now] = true;
    45         for(int j = 1;j <= n;j ++){
    46             if(!vis[j] && dis[j] > mp[now][j]){
    47                 dis[j] = mp[now][j];
    48                 pre[j] = now; 
    49             }
    50         }
    51     }
    52     return sumcost/sumlen;
    53 }
    54 int main(){
    55     while(cin>>n,n){
    56         for(int i = 1;i <= n;i ++){
    57             cin>>num[i].x>>num[i].y>>num[i].z;
    58         }
    59         for(int i = 1;i <= n;i ++){
    60             for(int j = i + 1;j <= n;j ++){
    61                 cost[j][i] = cost[i][j] = fabs(num[i].z - num[j].z);
    62                 len[i][j] = len[j][i] = cal(num[i].x,num[i].y,num[j].x,num[j].y);
    63             }
    64         }
    65         double sumlen = 0,sumcost = 0;
    66         for(int i = 2;i <= n;i ++){
    67             sumlen += len[1][i];
    68             sumcost += cost[1][i];
    69         }
    70         double x;
    71         double ans = sumcost/sumlen;
    72         while(1){
    73             x = ans;
    74             for(int i = 1;i <= n;i ++){
    75                 for(int j = i + 1;j <= n;j ++){
    76                     mp[j][i] = mp[i][j] = fabs(num[i].z - num[j].z) - x * cal(num[i].x,num[i].y,num[j].x,num[j].y);
    77                 }
    78             }
    79             ans = prim();
    80             if(fabs(ans - x) <= 0.0005) break;
    81         }
    82         cout<<fixed<<setprecision(3)<<ans<<endl;
    83     }
    84     return 0;
    85 } 
  • 相关阅读:
    HTML DOM 12 表格排序
    HTML DOM 10 常用场景
    HTML DOM 10 插入节点
    HTML DOM 09 替换节点
    HTML DOM 08 删除节点
    HTML DOM 07 创建节点
    022 注释
    024 数字类型
    005 基于面向对象设计一个简单的游戏
    021 花式赋值
  • 原文地址:https://www.cnblogs.com/Mingusu/p/12782599.html
Copyright © 2011-2022 走看看