poj2728 Desert King

最优比率生成树问题。

是完全图要用prim。顺便学了一发dinkelbach。二分1700ms+ 迭代200ms+很优秀

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n;
double X[1100],Y[1100],Z[1100];
double cst[1100][1100],dis[1100][1100];

double a[1100][1100],d[1100];
bool v[1100];
bool check(double mid)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) if(i!=j)
            a[i][j]=cst[i][j]-mid*dis[i][j];
    
    memset(v,false,sizeof(v));
    memset(d,0x7f,sizeof(d));
    for(int i=1;i<n;i++)
    {
        int x=-1;
        for(int j=1;j<=n;j++)
            if(v[j]==false&&(x==-1||d[x]>d[j]))x=j;
        v[x]=true;
        for(int y=1;y<=n;y++)
            if(v[y]==false)d[y]=min(d[y],a[x][y]);
    }
    double ans=0;
    for(int i=2;i<=n;i++)ans+=d[i];
    return (ans<0)||(fabs(ans)<1e-8);
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&X[i],&Y[i],&Z[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) if(i!=j)
            {
                cst[i][j]=fabs(Z[i]-Z[j]);
                dis[i][j]=sqrt( (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]) );
            }
            
        double l=0.0,r=100000.0;
        while(r-l>1e-5)
        {
            double mid=(l+r)/2;
            if(check(mid))r=mid;
            else l=mid;
        }
        printf("%.3lf\n",r);
    }
    return 0;
}
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n;
double X[1100],Y[1100],Z[1100];
double cst[1100][1100],dis[1100][1100];

double a[1100][1100],d[1100]; int p[1100];
bool v[1100];
double check(double mid)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) if(i!=j)
            a[i][j]=cst[i][j]-mid*dis[i][j];
    
    memset(v,false,sizeof(v));
    memset(d,0x7f,sizeof(d));
    for(int i=1;i<n;i++)
    {
        int x=-1;
        for(int j=1;j<=n;j++)
            if(v[j]==false&&(x==-1||d[x]>d[j]))x=j;
        v[x]=true;
        for(int y=1;y<=n;y++)
            if(v[y]==false)
            {
                if(d[y]>a[x][y])
                {
                    d[y]=a[x][y];
                    p[y]=x;
                }
            }
    }
    double sumc=0,sumd=0;
    for(int i=1;i<=n;i++)sumc+=cst[p[i]][i],sumd+=dis[p[i]][i];
    return sumc/sumd;
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&X[i],&Y[i],&Z[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) if(i!=j)
            {
                cst[i][j]=fabs(Z[i]-Z[j]);
                dis[i][j]=sqrt( (X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]) );
            }
            
        double A=0;
        while(1)
        {
            double B=check(A);
            if(fabs(A-B)<1e-8)break;
            else A=B;
        }
        printf("%.3lf\n",A);
    }
    return 0;
}

 

posted @ 2018-08-23 15:18  AKCqhzdy  阅读(139)  评论(0编辑  收藏  举报