• 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 } 
  • 相关阅读:
    display:table-cell,inline-block 之间的缝隙
    ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study(树状数组)
    ACM-ICPC 2018 徐州赛区网络预赛 J Maze Designer(最大生成树+LCA)
    1076 两条不相交的路径
    1107 斜率小于0的连线数量
    1112 KGold
    51nod 1110 距离之和最小V3
    1246 罐子和硬币
    1163 最高的奖励(贪心+优先队列)
    1028C:Rectangles
  • 原文地址:https://www.cnblogs.com/Mingusu/p/12782599.html
Copyright © 2020-2023  润新知