石油公司的油田往往包括多个油井,在为油田建造输油管道时,每个油井均需与主管道相连,如何确定管道的铺设方案,使得管道的总长度最小,即确定经费最省的建设方案是所要研究的问题。
问题一:针对各油井到主管道距离的各种不同情形,在设计时,需考虑共用管道与非共用管道费用相同与不同的问题
输油管道铺设要想使费用最省,必须是铺设线路最短,所以建立模型时必须保证油井与主管道距离之和最短,所以管道铺设费用最省问题就转化成了求最短线路的问题。
对于问题一,应该从有共用管线和全是非共用管线两个方面入手考虑,而且费用也会随着共用部分的长短而不同。
3.1模型的假设
(1)将油井本身的面积忽略不计,看成是质点,主管道看成是直线。
(2)在管道铺设的线路上,假设没有任何障碍,可以在任意位置铺设管道。
(3)不考虑油井的储油能力。
(4)假设管道费用仅仅与管道长度有关,而不考虑输油量。
3.2
符号说明
A1,A2,A3....An表示第i个油井Ai
S1,S2,S3....Sn表示第i个油井Ai与主管道之间的距离Si
x:油井的横坐标 (假设主管道是由东向西)
y:油井的纵坐标
mx:主管道的横坐标
my:主管道的纵坐标
假设主管道是由东向西,显然,主管道的铺设位置只和各油井位置的y坐标有关,设各个油井的y坐标为:y,主管道的纵坐标坐标为:my,各油井到主管道之间的输油管道长度总和应是:,要使这个值最小,主管道的位置y坐标应是各个油井y坐标的中位数。
证明(反证法):
①油井数目为奇数:假设主管道的最优位置y坐标值为y_val,不是各个油井位置y坐标的中位数y_median,我们可以假设y_val>y_median(不失一般性),y坐标小于y_val的油井数目为m,y坐标大于y_val的油井数目为n,显然有m>n。当我们将主管道位置下移距离x时(假设此时仍满足y_val>=y_median),各油井到主管道之间的输油管道长度总和应增加nx-mx,显然nx-mx<0(m>n),即存在一个比y_val更优的位置使得各油井到主管道之间的输油管道长度总和更小,这与假设矛盾。
②油井数目为偶数:证明情况同奇数情况。不同的是主管道的最优位置y坐标可以是各油井y坐标的两个中位数之间的任一整数。
5.1 递推过程的抽象描述
本设计采用快速排序和中位数来计算输油管道的最短路径。
5.2 主要数据类型与变量
x[ ]:存放油井横坐标的数组
a[ ] 、y[ ]:存放油井纵坐标的数组
5.3 算法或程序模块
void qsort(double a[],int l,int r) 对存放y坐标的数组进行从小到大的排序
void mcount(double a[],int n) 对排序后的y坐标取中位数并计算铺设的总长度
#include<iostream> #include<algorithm> #include<cmath> using namespace std; //交换a与b两个变量的值 void swap(int&a,int&b) { int t=a; a=b; b=t; } int partition(double a[],int l,int r) { int i = l-1,j=r; int v = a[r]; while(true) { while(a[++i]<v); while(a[--j]>v) if(j==l) break; if(i>=j)break; swap(a[i],a[j]); } swap(a[i],a[r]); return i; } void qsort(double a[],int l,int r) { int i; if(r<=l) return ; i=partition(a,l,r); qsort(a,l,i-1); qsort(a,i+1,r); } void mcount(double a[],int n) { double my;//主管道的y坐标 double mlength = 0,k; int i; //对油井的y坐标进行排序 qsort(a,0,n-1); if(n%2!=0) { //当个数为奇数时 my=a[n/2]; } else my = (double)(a[n/2-1]+a[n/2])/2;//个数为偶数 for(i = 0;i<n;i++) { mlength += fabs(my - a[i]); } cout<<my<<endl; cout<<mlength<<endl; } int main() { int n,i,j,sum=0; double x[100]; double y[100]; cout<<"请输入油井的个数"<<endl; cin>>n; for(i=0;i<n;i++) { cout<<"请输入油井"<<i+1<<"的坐标"<<endl; cin>>x[i]; cin>>y[i]; } mcount(y,n); for(i=0;i<n;i++) cout<<y[i]<<" "; return 0; }
原文:http://blog.csdn.net/qq544529563/article/details/24122837