您的位置:首页 > 其它

输油管道问题

2014-04-19 17:16 176 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: