1. 程式人生 > >POJ 2728 Desert King | 01分數規劃

POJ 2728 Desert King | 01分數規劃

最小 org 生成樹 .org blog spa 題目 mem span

題目:

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


題解:

二分比率,然後每條邊邊權變成w-mid*dis,用prim跑最小生成樹就行

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 1005
using namespace std;
int n,tot;
double x[N],y[N],z[N],dis[N];
bool vis[N];
double mul(double x) {return x*x;}
double
dist(int a,int b) { return sqrt(mul(x[a]-x[b])+mul(y[a]-y[b])); } bool check(double mid) { memset(vis,0,sizeof(vis)); for (int i=2;i<=n;i++) dis[i]=fabs(z[1]-z[i])-mid*dist(1,i); vis[1]=1; int tot=n-1; int id=-1; double val=0.0,tmp=0.0; while(tot--) { id=-1;
for (int i=1;i<=n;i++) { if(!vis[i]) { if(id==-1) id=i; else if(dis[id]>dis[i]) id=i; } } tmp+=dis[id]; vis[id]=1; for (int i=1;i<=n;i++) { if(!vis[i]) { dis[i]=min(dis[i],fabs(z[i]-z[id])-mid*dist(i,id)); } } }
return tmp<=0.0; } int main() { while (scanf("%d",&n)!=EOF) { if (!n) break; for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&x[i],&y[i],&z[i]); double l=0.0,r=0.0,mid; for (int i=2;i<=n;i++) r+=fabs(z[i]-z[1]); for(int i=1;i<=50;i++) { mid=(l+r)/2.0; if (check(mid)) r=mid; else l=mid; } printf("%.3lf\n",r); } return 0; }

POJ 2728 Desert King | 01分數規劃