POJ——2728(0/1分数规划)
最小生成树的分数规划
构成的图要是一棵生成树
可以发现我们要求的是
那么也就是要二分得到ans使刚好为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后面打了个分号
我可真是个小机灵鬼