【中位数扩展】 soldiers

传送门

题意

\(n\)名士兵,每个士兵的位置由一对整数\((x,y)\)来表示,士兵可以进行移动,每一次可以上下左右移动,
通过移动使所有士兵处于同一水平线,即\(y\)相同\(x\)相邻,每个士兵只能占据一个单独的位置,求总的最少的移动次数

数据范围

\(\begin{array}{l}1 \leq N \leq 10000 \\ -10000 \leq x[i], y[i] \leq 10000\end{array}\)

题解

\(y\)轴和\(x\)轴可以分开分别考虑,\(y\)轴方向上就是货仓选址选择中位数,
\(x\)轴方向上不允许有相同的,如果同样求中位数,不能满足,
对x进行排序后,要求使得士兵全部相邻的最小移动次数.那么在移动前和移动后,士兵的相对位置是不变的.
\(k\)为移动后的最左端的士兵的前一位置

  • \(x_{1} -> k+ 1\)

  • \(x_{2} -> k + 2\)

  • $\dots $

  • \(x_{n} -> k + n\)

\(x\)轴总共的移动距离即\(|x_{1}-k-1| + |x_{2}-k-2| + \dots + |x_{n}-k-n|\)
显然\(k\)\(x_{i}-i\)的中位数时候最小

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fi first
#define se second 
#define ll long long
#define pb push_back
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);


typedef pair<long long,long long> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef double db;


const ll mod=1e9+7;
const int N=1e4+10;

ll powmod(ll a,ll b,ll p)
{
    ll res=1;
    a%=p;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
ll gcd(ll a,ll b) 
{
    return b?gcd(b,a%b):a;
}


int _;
int x[N],y[N];
int n;

void solve()
{
    cin>>n;
    int ans=0;
    for(int i=1;i<=n;i++)
        cin>>x[i]>>y[i];
    sort(x+1,x+1+n);
        sort(y+1,y+1+n);
    for(int i = 1; i <= n; i++)
        x[i]-=i;
    sort(x+1,x+1+n);


    for(int i = 1; i <= n; i++)
        ans += abs(x[i] - x[(n+1)>>1]);

    for(int i = 1; i <= n; i++)
        ans += abs(y[i] - y[(n+1)>>1]);
    cout<<ans;
}
int main(){
    close;
    // cin>>_;
    // while(_--)
     solve();
}
posted @ 2020-09-22 09:33  Hyx'  阅读(132)  评论(0编辑  收藏  举报