poj2728 Desert King

大概題意:ios

  每兩個點中的邊權有兩個:一個是兩點座標的歐幾里得距離( horizontal distance),暫且成爲ai,第二個是兩點的海拔之差,稱爲bi.而後須要一個生成樹使sum(ai)\sum(bi)最小。git

 

這裏能夠引入分數規劃:咱們設ai\bi=k,那麼ai-bi*k=0算法

咱們只須要二分一個值mid,當ai-bi*mid=0時,這時的mid即是最優值。優化

對於每個mid,將每一條邊的邊權都變爲ai-bi*mid,而後求一個最小生成樹,若是總長是0,說明mid是答案,若是總長>0說明mid小了,讓mid變大,反之讓mid變小。spa

可是!!你覺得這樣就完了嗎?根本沒有!!!code

坑點:blog

一、這個點是一個徹底圖,也就是有足足n^2條邊,咱們使用的算法必定要盡力規避m,再見kruskal!,再見堆優化!甚至臨界表,再見!咱們必需要用沒有堆優化,使用鄰接矩陣的prim!ci

二、精度不能取0.0001或者0.001就ok了,必需要取到0.00001!get

三、二分時r必定不能開大,開打一點都會T,開到100就行,不要怕錯!!!string

四、終極大坑,最後的輸出不能用%lf,必須用%f,不要爲我爲何!廠長是我表哥!!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue> 
#include <cmath>
#include <cstdlib>
#define REP(i,k,n)  for(int i=k;i<=n;i++)
#define in(a) a=read()
#define MAXN 1000030 
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            f=-1;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}
int n; 
int x[1010],y[1010],d[1010];
int f[1010];
struct edge{
    int u,v;
    double a,b;
}old[10101010];
double map[1010][1010],dis[1010];
int vis[1010];
int total;
inline double check(double k){
    double sum=0;
    memset(dis,127,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(map,127,sizeof(map));
    REP(i,1,total)  map[old[i].v][old[i].u]=map[old[i].u][old[i].v]=old[i].a-k*old[i].b;
    dis[1]=0;
    for(int i=1;i<=n;i++){
        double minn=2147483647;
        int v=-1;
        for(int j=1;j<=n;j++)
            if(vis[j]==0 && (v==-1 || dis[j]<minn)){
                minn=dis[j];
                v=j;
            }
        sum+=dis[v];
        vis[v]=1;
        for(int j=1;j<=n;j++)
            if(dis[j]>map[v][j])
                dis[j]=map[v][j];
    }
    return sum;
}
int main(){
    while(cin>>n){
        if(!n)  break;
        total=0;
        REP(i,1,n)  in(x[i]),in(y[i]),in(d[i]),x[i]++,y[i]++,d[i]++;
        REP(i,1,n)
            REP(j,1,i-1){
               old[++total].a=abs(d[i]-d[j]);
               old[total].b=sqrt(abs(x[i]-x[j])*abs(x[i]-x[j])+abs(y[i]-y[j])*abs(y[i]-y[j]));
               old[total].u=i,old[total].v=j;
            }
        double l=0,r=100.0,mid,k;
        while(r-l>0.00001){
            mid=(l+r)/2;
            k=check(mid);
            if(k>0)  l=mid;
            if(k<0)  r=mid;
            if(k==0) break;
        }
        printf("%.3f\n",mid);
    }
    return 0;
}
/*
5
2 3 3
3 2 10
5 1 3
5 7 6
7 8 4
*/
相關文章
相關標籤/搜索