洛谷 P1889 士兵站队

洛谷 P1889 士兵站队

问题简述

这道题我们可以换另一种思路去看待它,就容易理解了:

在一个平面上,把 n 个点排列在一条与 x 轴平行的直线的整点上,且相邻两点的距离为 1

求一种排列方案,使得这n 个点到目标位置的 曼哈顿距离和最小

解法综述

由于是求曼哈顿距离,所以可以将 x ,y 分开考虑。

首先,要找到最优的一列(使移动步数最少的一列),其实就是要找一条平行于x轴的直线,设此直线为y=k,那么,每个点到这条线距离为|yik|,不难发现,当k是所有点纵坐标的中位数时,距离之和最小。

找到了这条直线之后,又该把每个点移到哪个位置才能使结果最优呢?

可以设最左边的点(第一个点)移动后的位置为b,因为所有点必须排在一条线段上,那么第二个点的移动后的位置即为b+1,第三个移动后的位置为b+2......以此类推,第n个点移动后的位置为b+n1

那么横向移动的步数之和为|x0b|+|x1b1|+|x2b2|+......+|xn1bn+1|,所以,要使步数之和最小,只需要 再找一次中位数 即可。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int x[N], y[N];

int n, res;
int main() {
    cin >> n;
    for (int i = 0; i < n; i++) cin >> x[i] >> y[i];

    sort(y, y + n);
    sort(x, x + n);

    for (int i = 0; i < n; i++) res += abs(y[i] - y[n / 2]); // 对与x轴的一条平等线的最短距离和

    for (int i = 0; i < n; i++) x[i] -= i;

    sort(x, x + n);
    for (int i = 0; i < n; i++) res += abs(x[i] - x[n / 2]);

    // 输出
    cout << res << endl;
    return 0;
}
posted @   糖豆爸爸  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2022-09-19 哈夫曼编码HuffmanCoding原理详解
2022-09-19 22张图带你深入剖析前缀、中缀、后缀表达式以及表达式求值
2021-09-19 P2615 神奇的幻方
2016-09-19 关于云主机拷贝复制资源异常的处理办法
Live2D
点击右上角即可分享
微信分享提示