输油管道问题

来源:互联网 发布:大数据时代面临的挑战 编辑:程序博客网 时间:2024/06/05 08:36

1.问题重述

石油公司的油田往往包括多个油井,在为油田建造输油管道时,每个油井均需与主管道相连,如何确定管道的铺设方案,使得管道的总长度最小,即确定经费最省的建设方案是所要研究的问题。

问题一:针对各油井到主管道距离的各种不同情形,在设计时,需考虑共用管道与非共用管道费用相同与不同的问题

2.问题分析

输油管道铺设要想使费用最省,必须是铺设线路最短,所以建立模型时必须保证油井与主管道距离之和最短,所以管道铺设费用最省问题就转化成了求最短线路的问题。

对于问题一,应该从有共用管线和全是非共用管线两个方面入手考虑,而且费用也会随着共用部分的长短而不同。

 

3.模型的假设与符号说明

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:主管道的纵坐标

4.模型建立

假设主管道是由东向西,显然,主管道的铺设位置只和各油井位置的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.c++程序实现

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;}


0 0