【中位数扩展】 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();
}