POJ 2728 Desert King (最小比率生成树,二分/迭代)
2011-11-04 21:00
393 查看
题意:沙漠里的王国需要修建水渠,连接国都与村庄····。说白了求一棵树,每个点有三个坐标(x,y,z)。边的benifit为两点之间的距离,cost为两点的高度差。现在要求一棵树使得 cost / benift 最小。
题解:很显然任意两点之间都有边,所以是一个很稠密的图。用Prime。二分的话2800ms+, 迭代300ms+。
#include <cmath> #include <iostream> using namespace std; #define MAX 1009 #define INF 99999999999 #define eps 1.0e-6 // 精度除以(0.001/2 ) struct NODE { int x, y, z; } node[MAX]; double e[MAX][MAX]; double dis[MAX]; bool vis[MAX]; void build_map ( int n, double l ) { for ( int i = 1; i <= n; i++ ) for ( int j = i + 1; j <= n; j++ ) { double len = sqrt(0.0 + (node[i].x-node[j].x) * (node[i].x-node[j].x) + (node[i].y-node[j].y) * (node[i].y-node [j].y)); double cost = fabs(0.0+node[i].z - node[j].z); e[i][j] = e[j][i] = cost - l * len; } } double prime ( int n ) { int i, j, k; double minc, ans = 0.0; for ( i = 1; i <= n; i++ ) { dis[i] = e[1][i]; vis[i] = false; } dis[1] = 0; vis[1] = true; for ( i = 2; i <= n; i++ ) { minc = INF; k = -1; for ( j = 1; j <= n; j++ ) { if ( !vis[j] && minc > dis[j] ) { minc = dis[j]; k = j; } } if ( minc == INF ) break; ans += minc; vis[k] = true; for ( j = 1; j <= n; j++ ) if ( ! vis[j] && dis[j] > e[k][j] ) dis[j] = e[k][j]; } return ans; } int main() { int n; while ( scanf("%d",&n) && n ) { for ( int i = 1; i <= n; i++ ) scanf("%d%d%d",&node[i].x, &node[i].y, &node [i].z); double mid, temp; double high = 100, low = 0.0; while ( 1 ) { mid = ( high + low ) / 2; build_map ( n, mid ) ; temp = prime ( n ); if ( fabs(temp) <= eps ) break; if ( temp < 0.0 ) high = mid - eps; else low = mid + eps; } printf("%.3lf\n",mid); } return 0; }
迭代法:
#include <cmath> #include <iostream> using namespace std; #define MAX 1001 #define INF 99999999999 #define eps 1.0e-6 struct NODE { int x, y, z; } node[MAX]; double edge[MAX][MAX]; double len[MAX][MAX]; double cost[MAX][MAX]; double dis[MAX]; bool vis[MAX]; int pre[MAX]; void build_map ( int n, double l ) { for ( int i = 1; i <= n; i++ ) for ( int j = i + 1; j <= n; j++ ) { len[i][j] = len[j][i] = sqrt(0.0 + (node[i].x-node[j].x) * (node[i].x-node[j].x) + (node[i].y-node[j].y) * (node[i].y-node[j].y)); cost[i][j] = cost[j][i] = fabs ( 0.0 + node[i].z - node[j].z); edge[i][j] = edge[j][i] = cost[i][j] - l * len[i][j]; } } double prime ( int n ) // 注意,与普通prime有区别 { int i, j, k; double minc, b = 0, c = 0; for ( i = 1; i <= n; i++ ) { dis[i] = edge[1][i]; pre[i] = 1; // 所有点的前驱初始化为1 vis[i] = false; } dis[1] = 0; vis[1] = true; for ( i = 2; i <= n; i++ ) { minc = INF; k = -1; for ( j = 1; j <= n; j++ ) { if ( ! vis[j] && minc > dis[j] ) { minc = dis[j]; k = j; } } if ( minc == INF ) break; b += len[pre[k]][k]; //********* c += cost[pre[k]][k]; //********* vis[k] = true; for ( j = 1; j <= n; j++ ) if ( ! vis[j] && dis[j] > edge[k][j] ) { dis[j] = edge[k][j]; pre[j] = k; //修改前驱 } } return c / b; } int main() { int n; while ( scanf("%d",&n) && n ) { for ( int i = 1; i <= n; i++ ) scanf("%d%d%d",&node[i].x, &node[i].y, &node[i].z); double a = 0, b; while ( 1 ) { build_map ( n, a ); b = prime ( n ); if ( fabs(b-a) <= eps ) break; a = b; } printf("%.3lf\n",b); } return 0; }
相关文章推荐
- poj_2728 Desert King(最优比率生成树+01分数规划+二分+prim)
- poj 2728 Desert King 【最优比例生成树 0-1分数规划】 【二分 or 迭代 + MST】
- poj 2728 Desert King 二分+O(n^2)最小生成树验证
- poj 2728 Desert King(最小比率生成树,迭代法)
- POJ 2728 Desert King(最优比率生成树) prim+二分
- POJ 2728 (最优比率生成树+二分或者迭代)
- 最优比率生成树 POJ 2728 迭代或者二分
- POJ-2728 Desert King 最小比率生成树
- POJ 2728 Desert King(01分数规划+二分+最小生成树-Prim)
- Desert King POJ - 2728 (最优比率生成树) 二分
- poj 2728 Desert King(最优比率生成树,01分数规划)
- POJ 2728 Desert King 最优比率生成树
- 【POJ】2728 Desert King 最优比率生成树——01分数规划【经典】
- poj 2728(最优比率生成树 二分)
- 【分数规划,最优比率生成树】POJ 2728 Desert King
- POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)
- POJ-2728 Desert King 01参数规划-最优比率生成树
- [POJ 2728][最优比率生成树] Desert King
- POJ 2728 Desert King(初遇最优比率生成树)
- POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)