P1889 士兵站队 题解

· · 题解

问题简述

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

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

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

解法综述

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

综上述可知,这道题其实是一道贪心题。

代码描述

#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
int n,x[10001],y[10001],ans;
void xsort(int l,int r)//用于将x轴上的士兵进行排序
{
    int i=l,j=r,m=x[(l+r)/2];
    while(i<=j)
    {
        while(x[i]<m) i++;
        while(x[j]>m) j--;
        if(i<=j)
        {
            swap(x[i],x[j]);
            i++;j--;
        }
    }
    if(l<j) xsort(l,j);
    if(i<r) xsort(i,r);
}
void ysort(int l,int r)//用于将y轴上的士兵进行排序
{
    int i=l,j=r,m=y[(l+r)/2];
    while(i<=j)
    {
        while(y[i]<m) i++;
        while(y[j]>m) j--;
        if(i<=j)
        {
            swap(y[i],y[j]);
            i++;j--;
        }
    }
    if(l<j) ysort(l,j);
    if(i<r) ysort(i,r);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);//输入当前士兵的坐标
    xsort(1,n);
    ysort(1,n);//将士兵的坐标进行排序
    for(int i=1;i<=n;i++) ans+=abs(y[i]-y[(n+1)/2]);//累加排序后士兵y坐标离y0的距离
    for(int i=1;i<=n;i++) x[i]=x[i]-i+1;
    xsort(1,n);//处理完士兵x坐标后需要再次排序
    for(int i=1;i<=n;i++) ans+=abs(x[i]-x[(n+1)/2]);//累加排序后士兵x坐标离x0的距离
    printf("%d",ans);//输出答案(为曼哈顿距离和最小)
    return 0;
}

这是本蒟蒻第一次写的题解,如有错误点请好心指出!

该题解审核通过后有人指出错误,已被修改 1 次。