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