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;
}

  

posted on 2012-08-06 15:07  夜->  阅读(174)  评论(0编辑  收藏  举报