铺设油井管道

铺设油井管道问题描述:

某石油公司有n口油井,为方便输送石油,计划修建输油管道。根据设计要求,水平方向有一条主管道,每口油井修一条垂直方向的支线管道通向主管道。请设计一种算法确定主管道的位置,使得所有油井到主管道之间的支线管道长度的总和最小。提示:复杂度为O(n)才能通过所有测试用例。
输入格式:
每个输入文件为一个测试用例,每个文件的第一行给出一个正整数n(1≤n≤1000000),表示油井数量,从第二行起的n行数据,表示每口油井的位置,每行包含以空格分隔的两个整数,分别表示每口油井的横坐标x(−10000≤x≤10000)和纵坐标y(−10000≤y≤10000)。

输出格式:
输出各油井到主管道之间的支管道最小长度总和。

求解思路

首先我们看完题目发现此题给的油井横坐标没有用,所以不用管它,然后要想求出所有油井到主管道之间的管道长度总和最小,就是求每个油井的纵坐标到主管道纵坐标的距离之和最小。然后根据数学知识我们可以得知,当主管道纵坐标为所有油井纵坐标所构成的数列的中位数时最小,所以我们只需要求出这组纵坐标数据的中位数即可。依照题目提示,时间复杂度得小于等于O(n)才行,所以我们选择用计数排序的方法

#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<iomanip>
#define ll long long
#define endl "\n"
using namespace std;
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
int t;
int n;
ll ans = 0;//距离总和
int a[20010];
int num[maxn];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);//关流使输入输出更快
	cin >> n;
	for (int i = 0; i < n; i++) {
		int x, y;
		cin >> x >> y;
		a[y + 10000]++;//利用这里和后面的for循环实现对纵坐标的排序
	}
	int h=0;
	for (int j = 0; j < 20010; j++) {
		if (a[j] != 0) {
			for (int i = 0; i < a[j]; i++)//部分油井可能有相同的纵坐标所以得用循环以免遗漏
				num[h++] = j - 10000;//用来存排序后的油井纵坐标
		}
	}
	for (int i = 0; i< n; i++) {
		ans += abs(num[n / 2] - num[i]);//abs用于求绝对值
	}
	cout << ans;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张仲颖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值