输油管道的实现

来源:互联网 发布:建筑设计软件 编辑:程序博客网 时间:2024/06/17 06:42

问题描述:

某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x坐标(东西向)和y坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置?证明可在线性时间内确定主管道的最优位置。


«编程任务:

给定n口油井的位置,编程计算各油井到主管道之间的输油管道最小长度总和。

 

示例:若n=5,各油井坐标分别为:(1,2)(2,2)(1,3)(3,-2)(3,3),主管道的最优位置的y坐标为2,各油井到主管道之间的输油管道最小长度总和为6。

 

解题思路

(1) 如何确定主管道的最优位置?

由于主管道是由东向西,显然,主管道的铺设位置只和各油井位置的y坐标有关,设各个油井的y坐标为: ,主管道的y坐标为:y,各油井到主管道之间的输油管道长度总和应是: ,要使这个值最小,主管道的位置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坐标的两个中位数之间的任一整数。

(2)算法实现及问题。


由于书上求第k小元素的算法可以在O(n)时间内完成。因此我们可以直接采用该算法来实现求各油井中位数。


#include<iostream>

#include<math.h>///这是fabs的头文件
#include<algorithm>///这是sort的头文件
#include<stdlib.h>
using namespace std;


void Init(int **y,int n)///初始化一维数组A,个数就是等差数列
{
  (*y)=(int*)malloc(sizeof(int)*(n*(n+1)/2));
}


void Delete(int *A)///销毁
 {
     free(A);
 }


void Input(int *y,int n)///输入油管道的x轴和y轴坐标(因为距离与x轴无关,所以可以把y【i】当做x进行输入)
{
    for(int i=0;i<n;i++)
    {
        cin>>y[i];///相当于输入x
        cin>>y[i];///相当于输入y
    }
}


int  Mid(int *y,int n)///进行排序并找出的中位数
{
    sort(y,y+n);///进行排序
    return y[n/2];///找出中位数
}


int main()
{
    int *y;
    int sum=0;///为输油管道的长度总和的最小位置
    int n;///表示输油管道的n个油井数
       cout<<"********************************************************"<<endl;
       cout<<"请输入输油管道的n个油井数为:"<<endl;
       cin>>n;
       Init(&y,n);
       cout<<endl<<"输入输油管道的每一个(x,y)坐标如下"<<endl;
       Input(y,n);
       int mid=Mid(y,n);///中位数
       for(int i=0;i<n;i++)///让输入的每个点的y轴与中位数进行相减
       {
       sum+=(int)fabs(y[i]-mid);/**这是求浮点数绝对值的函数*/
       }
       cout<<endl<<"输出输油管道的长度总和的最小位置为:"<<endl;
       cout<<sum;
       cout<<endl<<"********************************************************"<<endl<<endl<<endl;
       Delete(y);
       return 0;

}


原创粉丝点击