首页 > 代码库 > poj2728 Desert King --- 01分数规划 二分水果。。

poj2728 Desert King --- 01分数规划 二分水果。。

这题数据量较大,普通的求MST是会超时的。

d[i]=cost[i]-ans*dis[0][i]

据此二分。

但此题用Dinkelbach迭代更好


#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1010

double mp[N][N],c[N][N],x[N],y[N],z[N],e[N][N],d[N];
int vis[N],n;

inline double prim(double mid)
{
    double tmp,ans=0;
    for(int i=0;i<n;i++)
    {
        vis[i]=0;
        for(int j=0;j<i;j++)
            e[i][j]=e[j][i]=c[i][j]-mid*mp[i][j];
    }
    for(int i=1;i<n;i++)
        d[i]=e[0][i];
    d[0]=0;vis[0]=1;
    for(int i=1;i<n;i++)
    {
        int p;
        tmp=100000000;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&d[j]<tmp)
            {
                p=j;
                tmp=d[j];
            }
        }
        ans+=tmp;
        vis[p]=1;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&e[j][p]<d[j])
                d[j]=e[j][p];
        }
    }
    return ans;
}

int main()
{
    int i,j;
    double le,ri,mid;
    while(scanf("%d",&n)&&n)
    {
        for(i=0;i<n;i++)
            scanf("%lf%lf%lf",&x[i],&y[i],&z[i]);
        for(i=0;i<n;i++)
            for(j=0;j<i;j++)
            {
                mp[i][j]=mp[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                c[i][j]=c[j][i]=z[i]>z[j]?z[i]-z[j]:z[j]-z[i];
            }
        le=0;ri=1001;//不开心。。这样才能水过
        while(ri-le>1e-5)
        {
            mid=(le+ri)/2.0;
         //   printf("prim:%lf\n",prim(0,mid));
            if(prim(mid)>0)
                le=mid;
            else ri=mid;
        }
        printf("%.3f\n",mid);
    }
    return 0;
}