POJ2728 最小比率生成树/0-1分数规划/二分/迭代(迭代不会)
2014-08-08 11:33
627 查看
用01分数规划 + prime + 二分 竟然2950MS惊险的过了QAQ
前提是在TLE了好几次下过的 = =
题目意思:
有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目是要求一棵最优比率生成树。
解题思路:
对答案进行二分,当把代进去的答案拿来算最小生成树的时候,一旦总路径长度为0,就是需要的答案。
0-1规划是啥?
概念
有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T 最大(或最小).这显然是一个具有现实意义的问题.
解法之一 0-1分数规划
设x[i]等于1或0, 表示边e[i]是否属于生成树.
则我们所求的比率 r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m .
为了使 r 最大, 设计一个子问题---> 让 z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最大 (d[i] = benifit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.
然后明确两个性质:
1. z单调递减
证明: 因为cost为正数, 所以z随l的减小而增大.
2. z( max(r) ) = 0
证明: 若z( max(r) ) < 0, ∑(benifit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;
若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大.
贴代码:
前提是在TLE了好几次下过的 = =
题目意思:
有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目是要求一棵最优比率生成树。
解题思路:
对答案进行二分,当把代进去的答案拿来算最小生成树的时候,一旦总路径长度为0,就是需要的答案。
0-1规划是啥?
概念
有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T 最大(或最小).这显然是一个具有现实意义的问题.
解法之一 0-1分数规划
设x[i]等于1或0, 表示边e[i]是否属于生成树.
则我们所求的比率 r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m .
为了使 r 最大, 设计一个子问题---> 让 z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最大 (d[i] = benifit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.
然后明确两个性质:
1. z单调递减
证明: 因为cost为正数, 所以z随l的减小而增大.
2. z( max(r) ) = 0
证明: 若z( max(r) ) < 0, ∑(benifit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;
若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大.
贴代码:
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <climits> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <algorithm> #define ll long long using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 1001; struct node{ double x,y,h; }dot[MAXN]; double map[MAXN][MAXN]; int n; double dis(double x1,double y1,double x2,double y2){ return sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) ); } void creat(int n,double l){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=fabs(dot[i].h-dot[j].h) - l * dis(dot[i].x,dot[i].y,dot[j].x,dot[j].y); } double prim(){ bool vis[MAXN]; memset(vis, 0, sizeof(vis)); double dis[MAXN]; double ans = 0; int i,j; vis[1] = true; for(i = 1; i <= n; ++i) dis[i] = map[1][i]; for(i = 1; i < n; ++i){ int temp = INF, flag; for(j = 1; j <= n; ++j){ if(!vis[j] && dis[j] <= temp){ temp = dis[j]; flag = j; } } vis[flag] = true; ans += dis[flag]; for(j = 1; j <= n; ++j){ if(!vis[j] && map[flag][j] < dis[j]) dis[j] = map[flag][j]; } } return ans; } int main(){ int i,j; double res,front,rear, mid; while(EOF != scanf("%d",&n)){ if(n==0) break; for(i=1;i<=n;i++) scanf("%lf%lf%lf",&dot[i].x,&dot[i].y,&dot[i].h); front = 0; rear = 100.0;//doubt while(front <= rear){ mid = (front + rear) / 2; creat(n,mid); res = prim(); if(fabs(res) < 1e-4) break; else if(res > 1e-4) front = mid; else rear = mid; } printf("%.3f\n",mid); } return 0; }
相关文章推荐
- poj2728-最小比率生成树/0-1分数规划/二分/迭代
- poj2728 最小比率生成树——01分数规划
- 最小比例生成树(01分数规划)二分或迭代
- 最小比例生成树(01分数规划)二分或迭代
- 【分数规划-最小比例生成树】POJ2728[Desert King]题解
- poj_2728 Desert King(最优比率生成树+01分数规划+二分+prim)
- POJ 2728 Desert King (最小比率生成树,二分/迭代)
- POJ 2728 Desert King(01分数规划+二分+最小生成树-Prim)
- 【分数规划】【最优比率环 & 最优比率生成树】poj3621 Sightseeing Cows && poj2728 Desert King
- POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)
- poj 2728 Desert King 【最优比例生成树 0-1分数规划】 【二分 or 迭代 + MST】
- POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)
- 【POJ】2728 Desert King 最优比率生成树——01分数规划【经典】
- POJ 2728 Desert King(最优比率生成树 01分数规划)
- 【usaco-Earthquake, 2001 Open】 0-1分数规划 & 最优比率生成树
- POJ --- 2728 【最优比率生成树 --- 01分数规划】
- POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)
- POJ 2728 (最优比率生成树+二分或者迭代)
- 最优比率生成树 POJ 2728 迭代或者二分
- poj 2728 Desert King (最优比率生成树/01分数规划)