poj 2728 Desert King

http://poj.org/problem?id=2728

分数规划+二分   此题的图过于稠密 需要用prime 找最小生成树

代码:

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cmath>

#include<queue>

#include<string.h>



using namespace std;



const double eps=1e-5;

const int N=1001;

const double M=10000000000.0;

struct node

{

    int x,y;

    int h;

}mem[N];//输入点和高度

double d[N][N];//两点间 距离

int cost[N][N];//高度差

bool had[N];

double dist[N];

int n,m;

double findd(int i,int j)//返回距离

{

    return sqrt(1.0*(mem[i].x-mem[j].x)*(mem[i].x-mem[j].x)+

                1.0*(mem[i].y-mem[j].y)*(mem[i].y-mem[j].y));

}

bool prime(double L)//求最小生成树

{

    double ans=0.0;

    memset(had,false,sizeof(had));

    had[1]=true;

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

    dist[i]=cost[1][i]-L*d[1][i];

    for(int w=1;w<n;++w)

    {

        double MIN=M;

        int k=-1;

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

        {

            if(!had[i]&&dist[i]<MIN)

            {

                MIN=dist[i];

                k=i;

            }

        }

        ans+=MIN;

        had[k]=true;

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

        {

            if(!had[i]&&cost[k][i]-L*d[k][i]<dist[i])

            {

                dist[i]=cost[k][i]-L*d[k][i];

            }

        }

    }

    if(ans>0.0)

    return true;

    return false;



}

int main()

{

    //freopen("data.txt","r",stdin);

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

    {

        if(n==0)

        break;

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

        scanf("%d %d %d",&mem[i].x,&mem[i].y,&mem[i].h);

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

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

        {

            cost[i][j]=cost[j][i]=abs(mem[i].h-mem[j].h);//求花费

            d[i][j]=d[j][i]=findd(i,j);//求距离

        }

        double l=0.0,r=100.0;

        while(r-l>=eps)//二分缩紧

        {

            double mid=(l+r)/2.0;

            if(prime(mid))

            l=mid;

            else

            r=mid;

        }

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

    }

    return 0;

}

  

你可能感兴趣的:(des)