POJ——2728(0/1分数规划)

传送门

最小生成树的分数规划

构成的图要是一棵生成树

可以发现我们要求的是min(ΣΔhΣdis)min(\frac{ΣΔh}{Σdis})

那么也就是要二分得到ans使fans=Σ(disansΔhf(ans)=Σ(dis*ans-Δh)刚好为0

如果f(ans)>0,则r=mid,否则l=mid

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<cmath>
using namespace std;
#define inf 1e9
#define eps 1e-4
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
} 
#define ce(x) ((x)*(x))
double x[1005],y[1005],z[1005];
int n;
double h[1005][1005],dis[1005][1005];
bool vis[1005];
double w[1005];
double f[1005][1005];
inline bool prim(double k){
    double res=0.0;
    for(int i=1;i<=n;i++) w[i]=1e9;
    w[1]=0;
    memset(vis,false,sizeof(vis));
    memset(f,127,sizeof(f));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
        f[i][j]=h[i][j]-k*dis[i][j];
    }
//    for(int i=2;i<=n;i++)
//    printf("%.3lf\n",w[i]);
    for(int i=1;i<=n;i++){
        double minw=1e9;
        int p;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&w[j]<minw){
                minw=w[j],p=j;
            }
        }
        res+=minw,vis[p]=true;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&w[j]>f[p][j])
                w[j]=f[p][j];         
        }
    }
    return res>=0.0;
}
int main(){
    n=read();
    while(n!=0){
        for(int i=1;i<=n;i++)
        {
            x[i]=read(),y[i]=read(),z[i]=read();
        }
        double minv=inf,minc=inf,maxv=-inf,maxc=-inf;
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                dis[i][j]=dis[j][i]=sqrt(ce(x[i]-x[j])+ce(y[i]-y[j]));
                h[i][j]=h[j][i]=fabs((z[i]-z[j]));
                maxv=max(maxv,h[i][j]),minv=min(minv,h[i][j]);
                maxc=max(maxc,dis[i][j]),minc=min(minc,dis[i][j]);
            }
        }
        double l=0.0,r=40.0;
        while(l+eps<r){
            double mid=(l+r)/2.0;
            if(prim(mid)) l=mid;
            else r=mid;
        }
        printf("%.3lf\n",l);
        n=read();
    }
}

调了两个小时发现自己在if后面打了个分号

我可真是个小机灵鬼

posted @ 2018-10-11 20:04  Stargazer_cykoi  阅读(96)  评论(0编辑  收藏  举报