POJ 2728-Desert King(01分数规划_最优比率生成树)

来源:互联网 发布:阿里云 虚拟主机 美国 编辑:程序博客网 时间:2024/05/17 22:57

题目地址:POJ 2728
题意:将n个村庄连在一起,告诉每个村庄的三维坐标,村庄之间的距离为水平方向上的距离,花费为垂直方向上的高度差,求把村庄连接起来的最小的花费与长度之比为多少。
思路:最优比率生成树。和普通的01分数规划差不多的思路,只不过这道题的函数变成了一颗树而已。我是用二分查找来做的,迭代法的话请看这篇博客Fatedayt。话说二分确实慢,在最坏的上限的情况G++还是会T的。经检验貌似没有我想的那样的超级差的极限。。QAQ

#include <stdio.h>#include <math.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <sstream>#include <algorithm>#include <set>#include <queue>#include <stack>#include <map>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef __int64  LL;const int inf=0x3f3f3f3f;const double pi= acos(-1.0);const double esp=1e-7;const int maxn=1010;int n;struct node{    double x,y,z;}q[maxn];double d[maxn];int vis[maxn];double dis(int i,int j,double L){    return fabs(q[i].z-q[j].z)-L*sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y));}double prim(double L) {    int i,j,k,u;    double sum=0;    double Min;    memset(vis,0,sizeof(vis));    for(i=1;i<=n;i++)    d[i]=inf;    vis[1]=1;    d[1]=0;    u=1;    for(i=2;i<=n;i++){        Min=inf;        k=0;        for(j=1;j<=n;j++){            if(vis[j]) continue;            d[j]=min(d[j],dis(u,j,L)) ;            if(Min>d[j]) {                k=j;                Min=d[j];            }        }        sum+=Min;        vis[k]=1 ;        u=k;    }    return sum;}int main() {    int i,j;    double low,high,mid;    double maxx,minn;    while(~scanf("%d",&n)){        if(!n) break;        low=high=mid=0.0;        maxx=-inf;        minn=inf;        for(i=1;i<=n;i++){            scanf("%lf %lf %lf",&q[i].x,&q[i].y,&q[i].z);                minn=min(minn,q[i].z);                maxx=max(maxx,q[i].z);        }        high=maxx-minn;        while(high-low>esp){             mid=(low+high)/2;            if(prim(mid)>0)                low=mid;            else                high=mid;        }        printf("%.3f\n",low);    }    return 0 ;}
1 0
原创粉丝点击