poj2728 Desert King——01分数规划

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

第一道01分数规划题!(其实也蛮简单的)

这题也可以用迭代做(但是不会),这里用了二分;

由于比较裸,不作过多说明了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define eps 1e-6
using namespace std;
int const inf=0x3f3f3f;
int n;
double d[1005][1005],h[1005][1005],w[1005][1005],dis[1005];
double xx[1005],yy[1005],zz[1005];
bool vis[1005];
void add(int x,int y)
{
    double ds=sqrt((xx[x]-xx[y])*(xx[x]-xx[y])+(yy[x]-yy[y])*(yy[x]-yy[y]));
    d[x][y]=d[y][x]=ds;
    h[x][y]=h[y][x]=fabs(zz[x]-zz[y]);
}
double prim(double mid)
{
    double s=0;
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)
            w[i][j]=w[j][i]=h[i][j]-mid*d[i][j];
    for(int i=0;i<n;i++)vis[i]=0,dis[i]=inf;
    dis[0]=0;
    while(1)
    {
        int u=-1;
        for(int i=0;i<n;i++)
            if(!vis[i]&&(u==-1||dis[i]<dis[u]))u=i;
        if(u==-1)break;
        s+=dis[u];vis[u]=1;
        for(int i=0;i<n;i++)
            if(!vis[i])dis[i]=min(dis[i],w[u][i]);
    }
    return s;
}
int main()
{
    while(~scanf("%d",&n))
    {
        if(!n)return 0;
        for(int i=0;i<n;i++)
            scanf("%lf%lf%lf",&xx[i],&yy[i],&zz[i]);
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
                add(i,j);
        double l=0,r=100.00;//
        while(r-l>eps)
        {
            double mid=(l+r)/2;
            if(prim(mid)<eps)r=mid;//
            else l=mid;
        }
        printf("%.3lf\n",r);
    }
}

猜你喜欢

转载自www.cnblogs.com/Zinn/p/8948349.html