视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
输道问题(分治)
2025-10-06 05:59:21 责编:小OO
文档
1. 问题描述 

输道问题描述如下: 

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

2. 问题分析 

如果只有一口井,那么显然是越近越好,即建在油井上; 如果有两口井,那么显然是有以下三种情况:  

1.两口井都在主管道北边,那么这个时候的两个连接管道的长度和肯定大于两口井的Y坐标之差  

2.两口井都在主管道南边,和情况1是一样的  

3.两口井,一个在主管道南边,一个在主管道北边,那么两个连接管道的长度和就等于两口井的Y坐标之差  显然情况三是所要的最小管道长度的设计情况  

就是当主管道在两口井之间的任意位置时,连接管道长度之和都等于两口井的Y坐标之差,是最小的长度  

那么将这个结论推广,当有n口井的时候,  1.n是偶数  

只要这n口井分布在主管道的两边,一边n/2个,那么就是距离之和最小的  2.n是奇数  

只要将这n个井中,Y坐标最中间的(也就是Y是中值的那个)井不算,其余的偶数个井分布在主管道的两侧,这个时候移动主管道,那么这n个连接管道长度之和就决定于那个没有算的井了,因为其余的井的距离之和是固定了的,这个时候只要主管道最接近那个点就好了呀

3.数据结构设计 

用N来表示油井的数目,用数组s[]来记录N个油井的y坐标,通过对N%2的判断来判断N是否为偶数,如果是则用surt(N/2)来求路程,否则用(N+1)/2来求,对于surt()函数,是来计算路程的, 用while循环,把Y坐标大地的记录在数组的后面,最后用zdlch()函数通过对sumin的累加来计算最小的长度之和。

4.算法设计

int i;

while(j!=k){   

b=s[0];   

for(i=0;i  if(s[i]>=b){   

b=s[i];    

l=i; 

 }   

}   

m=s[l];  

s[l]=s[a-1];  

s[a-1]=m;  

a--;  

j++;  

5.程序设计 

输道问题程序如下: 

#include 

#include 

void suanfa(); 

void zdlch(int b); 

void surt(int k); 

int N;//全局变量 油井数 

int s[100];//n个油井y轴坐标 

int sumin;//输道最小长度  

void main() {  

int i;  

sumin=0;  

scanf("%d",&N);  

for(i=0;iscanf("%d",&s[i]);   

scanf("%d",&s[i]); 

 } 

suanfa();//调用关键算法函数  

printf("%d\\n",sumin); }  

void suanfa() {  

if(N%2==0)//当油井数是偶数时   

surt(N/2); 

else   

surt((N+1)/2);//油井是奇数时 

}  

void surt(int k)//从大到小第k个数是b调用suanfa(b)函数求出路程  {  

int j=0,b,l,m;  

int a=N;  

int i;  

while(j!=k) {    

b=s[0];   

for(i=0;iif(s[i]>=b)    

b=s[i];     

l=i; 

   } 

m=s[l];s[l]=s[a-1];s[a-1]=m;a--;j++; 

 zdlch(b); 

}  

Void zdlch(int b)      //求最小长度的总和                                          {   

int i;  

for(i=0;isumin=sumin+(int)fabs(b-s[i]); 

}下载本文

显示全文
专题