デザートキングPOJ-2728

題名:

N平面上の点の座標とその重みが与えられると、任意の2点間のエッジの値はそれらの距離であり、コストは2つの点の重み間の差の絶対値です。グラフ、ツリーのすべてのエッジの値の合計に対するコストの合計の比率を最小化します(この比率のみが必要です)

回答:

詳細は、この2番目のモデル
01スコアプログラミングモデルを見ることができます。ei∈Tの場合はxi = 1 xi = 0、それ以外の場合は
二分法の回答r r
に対する回答を検証する方法は?
エッジの重み付けans [i] = value [i] -r * cost [i]
スパニングツリーであるため、エッジの数が決定されます。したがって、max {f(r)}は最初のn-1 ans [を取る必要があります。 i]、つまり、最大全域木を見つけ、最大全域木の重みの正と負に応じて2つに分割します。最小化は、最小全域木を見つけることです。
ここにいくつかのポイントがあります。While(rl> = 1e-5)
二分ループで使用されます。prim(密なグラフであるため)最小全域木を見つけるために

コード:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define sqr(x) (1.0*(x)*(x))
#define RG register
#define MAX 1111
inline int read()
{
    
    
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int n,x[MAX],y[MAX],z[MAX];
double dis[MAX];
double len[MAX][MAX],cost[MAX][MAX],g[MAX][MAX];
bool vis[MAX];
bool check(double mid)
{
    
    
    for(int i=0;i<=n;++i)dis[i]=1e20,vis[i]=false;
    dis[1]=0;double tot=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            g[i][j]=cost[i][j]-mid*len[i][j];
    for(int i=1;i<=n;++i)
    {
    
    
        int u=0;
        for(int j=1;j<=n;++j)if(!vis[j]&&dis[j]<dis[u])u=j;
        vis[u]=true;tot+=dis[u];
        for(int j=1;j<=n;++j)
            if(!vis[j])
                dis[j]=min(dis[j],g[u][j]);
    }
    return tot<=0;
}
int main()
{
    
    
    while(n=read())
    {
    
    
        for(int i=1;i<=n;++i)x[i]=read(),y[i]=read(),z[i]=read();
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            {
    
    
            	len[i][j]=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
				cost[i][j]=abs(z[i]-z[j]);
			}
                

        double l=0,r=1e5;
        while(r-l>=1e-5)
        {
    
    
            double mid=(l+r)/2;
            if(check(mid))r=mid;
            else l=mid;
        }
        printf("%.3f\n",l);
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/qq_35975367/article/details/115146018