题目背景
听说最近石油危机
所以想到了这题
题目描述
某石油公司计划建造一条由东向西的主要输油管道。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路径(或南或北)与主管道相连。如果给定n口油井的位置,及它们的x坐标(东西向)和y坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置?证明可规定时间内确定主管道的最优位置。
输入格式
第一行是油井数n(1<=n<=10000)
接下来n行是油井的位置,每行2个整数x和y(-10000<=x,y<=10000)
输出格式
只有一行
是油井到主管道之间的输油管道最小长度总和
输入输出样例
输入 #1 复制
5
1 2
2 2
1 3
3 -2
3 3
输出 #1 复制
6
中位数的应用,中位数就是在一个有序的序列里面中间的那个数,这个是小学的知识,我小学也学了,然后看到这个题我还是很懵的,看了题解别人说是中位数做的,我一脸懵逼(小学只知道中位数的概念而已),然后我找到了中位数这样一条性质:
中位数性质:所有数与中位数的绝对值之差的和最小。
然后想了想确实是这么回事,看到这个题目你可以想象一下在二维直角坐标系下有一根水平的管子,然后有n个点,现在要你求这n个点到管子的最小长度之和根据中位数的性质很容易可以将代码写出来,关键是你会知道这条性质(菜菜的我表示小学白学了),ac代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + 10;
int y[maxn], x[maxn];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x[i]>>y[i];
}
sort(y, y + n);
int m = y[n / 2];//中位数
int ans = 0;
for (int i = 0; i < n; i++) {
ans += abs(m - y[i]);//在y轴各点距离等于绝对值|y-yi|,将他们累加起来
}
cout << ans << endl;
}
P1889 士兵站队
在一个划分成网格的操场上, n个士兵散乱地站在网格点上。由整数 坐标 (x,y) 表示。士兵们可以沿网格边上、下左右移动一步,但在同时刻任一网格点上只能有名士兵。按照军官的命令,们要整齐地列成个水平队列,即排成 队列,即排成 (x,y),(x+1,y), …,(x+n -1,y) 。如何选择 x 和y的值才能使 士兵们以最少的总移动步数排成一列。
输入格式
文件的第 1 行是士兵数 n,1≤n≤10000 。接下来 n 行是士兵的初始位置, 每行 2 个整数 x 和y,-10000 ≤x,y≤10000 。
输出格式
文件中 只有一个整 数是士兵排成一行需要的最少移动步。
输入输出样例
输入 #1 复制
5
1 2
2 2
1 3
3 -2
3 3
输出 #1 复制
8
这个题也是最小距离之和,也是中位数的应用题,不同的是它还要保证在一条水平线上,所以我们还需要将x的值稍稍变动一下,具体我写在代码注释里面。
ac代码:
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + 10;
int x[maxn];
int y[maxn];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x[i] >> y[i];
}
int ans = 0;
sort(x, x + n);
for (int i = 0; i < n; i++) {//将x轴的点分别移动连续不同距离点保证他们能在一条水平线上面
x[i] -= i;
}
sort(x, x + n);
sort(y, y + n);
int m = y[n / 2];//y轴中位数
int m1 = x[n / 2];//x轴中位数
for (int i = 0; i < n; i++) {
ans += abs(m - y[i]);
ans += abs(m1 - x[i]);
}
cout << ans << endl;
}