【POJ 2728】Desert King (最优比例生成树)

传送门here

这是一道01分数规划之最优比例生成树的入门题

类似的 我们对于每次check 预处理d数组(代码里是lowcost[])由于是稠密图 跑一遍prim

由于prim就是通过贪心,保证每次选的边最优来做的,所以只用统计最小生成树的权值有没有大于0

#include<iostream>
#include<cstring>
#include<cmath>
#include<iomanip>
#define N 1005
#define eps 1e-6
#define INF 0x7fffffff
using namespace std;
int n;
double x[N],y[N],z[N],dis[N][N],cost[N][N],lowcost[N];
bool vis[N];
inline bool check(double a)
{
    memset(lowcost,0,sizeof(lowcost));
    memset(vis,false,sizeof(vis));
    double sum=0;
    int pos=-1;
    vis[1]=true;
    for(int i=1;i<=n;i++)    lowcost[i]=cost[1][i]-a*dis[1][i];
    for(int i=1;i<n;i++)
    {
        double minv=INF;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&lowcost[j]<minv)
            {
                pos=j;
                minv=lowcost[j];
            }
        }
        vis[pos]=true;
        sum+=minv;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&cost[pos][j]-a*dis[pos][j]<lowcost[j])
                lowcost[j]=cost[pos][j]-a*dis[pos][j];
        }
    }
    if(sum>=0)    return true;
    else return false;
}
int main()
{
    while(cin>>n&&n)
    {
        memset(x,0,sizeof(x));    memset(y,0,sizeof(y));    memset(z,0,sizeof(z));
        memset(dis,0,sizeof(dis));    memset(cost,0,sizeof(cost));    
        for(int i=1;i<=n;i++)    cin>>x[i]>>y[i]>>z[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                cost[i][j]=fabs(z[i]-z[j]);
            }
        }
        double l=0,r=1000;
        while(l+eps<r)
        {
            double m=(l+r)/2;
            if(check(m))    l=m;
            else r=m;
        }
        cout<<fixed<<setprecision(3)<<l<<'\n';
    }
    return 0;
} 

 

posted @ 2018-10-13 09:31  Patrickpwq  阅读(109)  评论(0编辑  收藏  举报