poj 2728(最小比率生成树)
2012-08-04 22:39
309 查看
参考题解:http://www.cppblog.com/jh818012/articles/167743.html
题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,
建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差
现在要求方案使得费用与距离的比值最小
很显然,这个题目是要求一棵最优比率生成树,
0-1分数规划,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最大.
View Code
题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,
建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差
现在要求方案使得费用与距离的比值最小
很显然,这个题目是要求一棵最优比率生成树,
0-1分数规划,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最大.
View Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; #define N 1010 #define MAX 999999999 const double eps=1e-4; int n; int vis ,x ,y ,z ,pre ; double dis ,cost ,dist ; double prim(double x){ double totalcost=0,totaldist=0; for(int i=1;i<=n;i++){ pre[i]=1; } dis[1]=0; memset(vis,0,sizeof(vis)); vis[1]=1; for(int i=2;i<=n;i++){ dis[i]=cost[1][i]-dist[1][i]*x; } int k; for(int i=2;i<=n;i++){ double mincost=MAX; for(int j=2;j<=n;j++){ if(!vis[j]&&dis[j]<mincost){ mincost=dis[j]; k=j; } } vis[k]=1; totalcost+=cost[pre[k]][k]; totaldist+=dist[pre[k]][k]; for(int j=1;j<=n;j++){ if(!vis[j]&&dis[j]>cost[k][j]-dist[k][j]*x){ dis[j]=cost[k][j]-dist[k][j]*x; pre[j]=k; } } } return totalcost/totaldist; } int main(){ while(scanf("%d",&n),n){ for(int i=1;i<=n;i++){ scanf("%d%d%d",&x[i],&y[i],&z[i]); for(int j=1;j<i;j++){ double t=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); cost[i][j]=cost[j][i]=abs(z[i]-z[j]); dist[i][j]=dist[j][i]=sqrt(t); } } double a=0; while(1){ double b=prim(a); if(abs(a-b)<eps)break; else a=b; //cout<<a<<endl; } printf("%.3f\n",a); } return 0; }
相关文章推荐
- poj 2728 最优比率树(最小生成树问题)
- POJ 2728 Desert King (最小比率生成树,二分/迭代)
- POJ-2728 Desert King 最小比率生成树
- POJ 2728 最小生成树 求最优比率生成树
- poj 2728 Desert King(最小比率生成树,迭代法)
- poj2728--Desert King(最优比率生成树)
- POJ 2728 Desert King 最优比率生成树
- POJ 2728 Desert King 01分数规划 最优比率生成树
- 最优比率生成树 POJ 2728 迭代或者二分
- poj 2728 最优比率生成树
- POJ 2728 Desert King(最优比率生成树 01分数规划)
- POJ 2728 最优比率生成树
- POJ 2728 最优比率生成树
- POJ 2728-Desert King(01分数规划_最优比率生成树)
- poj 2728(最优比率生成树 二分)
- POJ 2728 Desert King(最优比率生成树)
- poj 2728 Desert King (最优比率生成树/01分数规划)
- POJ 2728 最优比率生成树
- poj-2728-Desert King-01分数规划+最小生成树
- poj2728 最优比率生成树