输油管道做题报告

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

这道题首先可以看出跟x坐标没关系,然后我为了找最小值本来还想二分。其实正解是排序后y坐标直接取中位数作为主管道的位置即可

1|0中位数

1|1中位数的性质

给定一个数列,中位数有这样的性质 :所有数与中位数的绝对差之和最小

1|2中位数性质的简单证明

首先,给定一个从小到大的数列x1,x2,……,xn,设x是从x1xn与其绝对差之和最小的数,则显然x位于x1xn之间。那么,由于x1,xn与它们之间的任意一点的距离之和都相等,且都等于xnx1,因此接下来可以不考虑x1xn,而考虑剩下的从x2xn1的数,同样显然有x必然位于x2xn1之间,依次类推,最后得出的结论是x就是该数列中间的那个数,或者是中间的那两个数之一,而这个数就是中位数。

结论:数列的中位数就是该数列各个数与其绝对差之和最小的数。

code

#include <cstdio> #include <algorithm> inline void read(int &x) { x=0;char ch=0;bool sign=false; while(ch<'0' || ch>'9') { sign|=(ch== '-'); ch=getchar(); } while(! (ch<'0' || ch>'9')) { x=x*10+(ch^48); ch=getchar(); } x=sign? -x : x; } inline void print(long long x) { if(x<0)putchar('-'),x=-x; if(x>9)print(x/10); putchar(x%10+'0'); } struct node { int x,y; bool operator < (const node & rhs)const{ return y<rhs.y; } }a[110000]; int n; int sum; int ans; inline int abs(int x) { return x>0?x:-x; } int main() { freopen("pipe.in","r",stdin); freopen("pipe.out","w",stdout); read(n); for(int i=1; i<=n; i++) { read(a[i].x),read(a[i].y); } std::sort(a+1,a+n+1); int temp=a[(n+1)/2].y; int ans=0; for(int i=1; i<(n+1)/2; i++) { ans+=abs(temp-a[i].y); } for(int i=(n+1)/2+1; i<=n; i++) { ans+=abs(temp-a[i].y); } print(ans); }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17776994.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(49)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示