• POJ 2728 01分数规划


    题意:
    最优比率生成树,要求生成树中的所有边的花费与所有边的长度的比值最小

    题解:

    01分数规划,详见http://www.cnblogs.com/proverbs/archive/2013/01/09/2853725.html

    网上都是写的最小生成树,其实最大生成树也可以,其实写什么都一样,关键是根据公式的不等号方向判断~

    最小生成树:

    View Code
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 #define N 1100
     9 const double INF=99999999.0;
    10 
    11 using namespace std;
    12 
    13 double sx[N],sy[N],sz[N],cost[N][N],map[N][N],dis[N];
    14 double l,r,mid;
    15 bool vis[N];
    16 int n;
    17 
    18 inline double getdis(int a,int b)
    19 {
    20     return sqrt((sx[a]-sx[b])*(sx[a]-sx[b])+(sy[a]-sy[b])*(sy[a]-sy[b]));
    21 }
    22 
    23 inline void read()
    24 {
    25     for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&sx[i],&sy[i],&sz[i]);
    26     for(int i=1;i<=n;i++)
    27         for(int j=i+1;j<=n;j++)
    28         {
    29             map[i][j]=map[j][i]=getdis(i,j);
    30             cost[i][j]=cost[j][i]=abs(sz[i]-sz[j]);
    31         }
    32 }
    33 
    34 inline bool check()//最小生成树 
    35 {
    36     for(int i=1;i<=n;i++) dis[i]=INF;
    37     dis[1]=0.0;
    38     memset(vis,false,sizeof vis);
    39     double slen=0.0,mindis;
    40     for(int j=1,k;j<=n;j++)
    41     {
    42         mindis=INF;
    43         for(int i=1;i<=n;i++)
    44             if(!vis[i]&&mindis>dis[i]) mindis=dis[i],k=i;
    45         vis[k]=true; slen+=mindis;
    46         for(int i=1;i<=n;i++)
    47             if(!vis[i]&&cost[k][i]-mid*map[k][i]<dis[i]) dis[i]=cost[k][i]-mid*map[k][i];
    48     }
    49     if(slen>=0) return true;
    50     return false;
    51 }
    52 
    53 inline void go()
    54 {
    55     l=0.0,r=1010.0;
    56     while(r-l>=1e-8)
    57     {
    58         mid=(l+r)/2.0;
    59         if(check()) l=mid;
    60         else r=mid;
    61     }
    62     printf("%.3lf\n",mid);
    63 }
    64 
    65 int main()
    66 {
    67     while(scanf("%d",&n),n) read(),go();
    68     return 0;
    69 }

    最大生成树:

    View Code
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 #define N 1100
     9 const double INF=99999999.0;
    10 
    11 using namespace std;
    12 
    13 double sx[N],sy[N],sz[N],cost[N][N],map[N][N],dis[N];
    14 double l,r,mid;
    15 bool vis[N];
    16 int n;
    17 
    18 inline double getdis(int a,int b)
    19 {
    20     return sqrt((sx[a]-sx[b])*(sx[a]-sx[b])+(sy[a]-sy[b])*(sy[a]-sy[b]));
    21 }
    22 
    23 inline void read()
    24 {
    25     for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&sx[i],&sy[i],&sz[i]);
    26     for(int i=1;i<=n;i++)
    27         for(int j=i+1;j<=n;j++)
    28         {
    29             map[i][j]=map[j][i]=getdis(i,j);
    30             cost[i][j]=cost[j][i]=abs(sz[i]-sz[j]);
    31         }
    32 }
    33 
    34 inline bool check()//最大生成树 
    35 {
    36     for(int i=1;i<=n;i++) dis[i]=-INF;
    37     dis[1]=0.0;
    38     memset(vis,false,sizeof vis);
    39     double slen=0.0,maxdis;
    40     for(int j=1,k;j<=n;j++)
    41     {
    42         maxdis=-INF;
    43         for(int i=1;i<=n;i++)
    44             if(!vis[i]&&maxdis<dis[i]) maxdis=dis[i],k=i;
    45         vis[k]=true; slen+=maxdis;
    46         for(int i=1;i<=n;i++)
    47             if(!vis[i]&&mid*map[k][i]-cost[k][i]>dis[i]) dis[i]=mid*map[k][i]-cost[k][i];
    48     }
    49     if(slen>=0) return true;
    50     return false;
    51 }
    52 
    53 inline void go()
    54 {
    55     l=0.0,r=1010.0;
    56     while(r-l>=1e-8)
    57     {
    58         mid=(l+r)/2.0;
    59         if(check()) r=mid;
    60         else l=mid;
    61     }
    62     printf("%.3lf\n",mid);
    63 }
    64 
    65 int main()
    66 {
    67     while(scanf("%d",&n),n) read(),go();
    68     return 0;
    69 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数+NTT)
    CF960G Bandit Blues(第一类斯特林数)
    loj#2542. 「PKUWC2018」随机游走(树形dp+Min-Max容斥)
    mysql修改原始密码
    MySQL基础命令小结
    pip安装python包出错:Could not find a version that satisfies the requirement skimage (from versions: )
    python 安装whl文件
    python中使用anaconda对不平衡数据的处理包imblearn的安装
    数据分析-合辑
    No module named ‘sklearn.model_selection解决办法
  • 原文地址:https://www.cnblogs.com/proverbs/p/2853745.html
Copyright © 2020-2023  润新知