POJ2728:最优比率生成树

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

题意:传送门

 原题目描述在最下面。
 三维坐标下给你n个点,两个点之间的距离是平面欧式距离,两个点之间的花费是高度差。
 求一颗生成树使得费用和距离的比值最小。

思路:

 不是很懂唉,什么01分数规划。

 这题就是二分比率m, m = c o s t / d i s ( c o s t d i s × m ) 大于0表示比率m还可以更大,反之m要变小才行。

 二分跑了 1641 m s .

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#include<bitset>
#include<cmath>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const int N = (int)1e3 +107;
int n;
double dis[N], ar[N][N];
int vis[N];
struct lp{
  int x,y,h;
}cw[N*N];
double len(int x1,int y1,int x2,int y2){
  return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)*1.0);
}
bool prim(double m){
  for(int i=1;i<=n;++i){
    dis[i] = INF;
    vis[i] = 0;
  }
  double res = 0;
  dis[1] = 0;
  for(int t=1;t;++t){
    double mmax=INF;
    int p = -1;
    for(int i=1;i<=n;++i){
      if(vis[i]==0&&mmax>dis[i]){
        mmax = dis[i];
        p = i;
      }
    }
    if(p==-1)break;
    res+=mmax;
    vis[p]=1;
    for(int i=1;i<=n;++i){
      if(vis[i]==0&&dis[i]>fabs(cw[i].h*1.0-cw[p].h) - ar[p][i]*m){
        dis[i] = fabs(cw[i].h*1.0-cw[p].h) - ar[p][i]*m;
      }
    }
  }
  return res>=0;
}
int main(){
  while(~scanf("%d", &n)&&n){
    for(int i=1;i<=n;++i){
      scanf("%d%d%d",&cw[i].x,&cw[i].y,&cw[i].h);
    }
    for(int i=1;i<=n;++i){
      for(int j=i;j<=n;++j){
        ar[i][j]=ar[j][i]=len(cw[i].x,cw[i].y,cw[j].x,cw[j].y);
      }
    }
    double l=0,r=200,mid;
    while(r-l>eps){
      mid=(l+r)/2;
      if(prim(mid))l=mid;
      else r=mid;
    }
    printf("%.3f\n", r);
  }
  return 0;
}


原题目描述:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/81321170