zoukankan      html  css  js  c++  java
  • POJ 2728 Desert King

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

      题目大意是:给你坐标上一些点,然后你需要用一些边把他们连接起来,边有费用和长度,求总费用和总长度最小比值。

      即最优比率生成树,用01分数规划的Dinkelbach算法解决。

      问题目标求 MIN( ∑CiXi / ∑DiXi ) Xi∈{0,1} ,设r=∑CiXi / ∑DiXi ,可得∑CiXi - ∑DiXi * r=0.

      设Q(r)=∑CiXi - ∑DiXi * r = ∑(CiXi - DiXi*r), 即当Q(r)无限逼近0时得到问题的极值,所以我们将边权转化为(Ci-Di*r)不断求最小生成树即可。

     

      (废话:为什么说这个算法是迭代……因为MST的返回值也是一个r,所以我们用当前解去限制下一次计算,就迭代了……纠结半天……另外Dinkelbach算法的收敛速度是超越二分的)

      

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #define sqr(r) (r)*(r)
    #define eps 1e-6
    #define mn 1001
    using namespace std;
    
    const double inf=100000000.0;
    
    int n,pre[mn];
    double dist[mn][mn],d[mn],cost[mn][mn];
    bool vis[mn];
    struct POSITION{
    	int x,y,z;
    }pos[mn];
    
    double prim(double x){
    	double cur_cost=0,cur_dist=0,mind;
    	memset(vis,false,sizeof(vis));
    	d[1]=0,pre[1]=0,vis[1]=true;
    	for(int i=2;i<=n;i++)
    		d[i]=cost[1][i]-dist[1][i]*x,pre[i]=1;
    	for(int k=1;k<n;k++){
    		int minp;mind=inf;
    		for(int i=2;i<=n;i++)
    			if(!vis[i] && mind>d[i])
    				mind=d[i],minp=i;
    		vis[minp]=true;
    		cur_cost+=cost[pre[minp]][minp];
    		cur_dist+=dist[pre[minp]][minp];
    		for(int i=2;i<=n;i++)
    			if(!vis[i] && d[i]>cost[minp][i]-dist[minp][i]*x)
    				d[i]=cost[minp][i]-dist[minp][i]*x,pre[i]=minp;
    	}
    	return cur_cost/cur_dist;
    }
    
    int main(){
    	while(scanf("%d",&n),n!=0){
    		memset(cost,0,sizeof(cost));
    		memset(dist,0,sizeof(dist));
    		for(int i=1;i<=n;i++) scanf("%d%d%d",&pos[i].x,&pos[i].y,&pos[i].z);
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				dist[i][j]=sqrt((double)sqr(pos[i].x-pos[j].x)+(double)sqr(pos[i].y-pos[j].y)),
    				cost[i][j]=abs(pos[i].z-pos[j].z);
    		double a=0,b;
    		while(true){
    			b=prim(a);
    			if(fabs(b-a)<eps) break;
    			a=b;
    		}
    		printf("%.3lf\n",a);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    【洛谷P1119】灾后重建
    【洛谷P1462】通往奥格瑞玛的道路
    【洛谷P1991】无线通讯网
    poj 2892(二分+树状数组)
    hdu 1541(树状数组)
    hdu 5059(模拟)
    hdu 5056(尺取法思路题)
    poj 2100(尺取法)
    hdu 2739(尺取法)
    poj 3320(尺取法)
  • 原文地址:https://www.cnblogs.com/Delostik/p/2118848.html
Copyright © 2011-2022 走看看