题意:一些士兵站在矩阵的一些方格内,现要把他们移动到一横排,并连续地排成一队,问最少需要移动多少步。
分析:先将他们移动到同一横排,这横排应该是他们纵坐标的中位数,才能使得此过程总步数最少。然后要把他们紧凑起来。我们先把横坐标排序,并假设起点是a,那么我们就是要求i=1~n,abs(a+i - xi)的加和。即i=1~n,abs(a-(xi - i))的加和。我们构建一个新数列zi = xi - i,当a 等于z的中位数时原式的值最小。
综上我们可以得到一个普遍结论,就是对于一个数列Xi(i=1~n),取一个X使得i=1~n时abs(Xi-A)的加和最小,那么A应该是数列Xi的中位数。Xi不一定是直接给出的,可能是一个关于已知量的表达式。
View Code
#include
<
iostream
>
#include < cstdio >
#include < cstdlib >
#include < cstring >
#include < algorithm >
using namespace std;
#define maxn 10004
int n;
int x[maxn], y[maxn];
int main()
{
// freopen("t.txt", "r", stdin);
scanf( " %d " , & n);
for ( int i = 0 ; i < n; i ++ )
scanf( " %d%d " , & x[i], & y[i]);
sort(y, y + n);
sort(x, x + n);
for ( int i = 0 ; i < n; i ++ )
x[i] -= i;
sort(x, x + n);
int a = (n + 1 ) / 2 - 1 ;
int ans = 0 ;
for ( int i = 0 ; i < n; i ++ )
ans += abs(y[a] - y[i]) + abs(x[a] - x[i]);
printf( " %d\n " , ans);
return 0 ;
}
#include < cstdio >
#include < cstdlib >
#include < cstring >
#include < algorithm >
using namespace std;
#define maxn 10004
int n;
int x[maxn], y[maxn];
int main()
{
// freopen("t.txt", "r", stdin);
scanf( " %d " , & n);
for ( int i = 0 ; i < n; i ++ )
scanf( " %d%d " , & x[i], & y[i]);
sort(y, y + n);
sort(x, x + n);
for ( int i = 0 ; i < n; i ++ )
x[i] -= i;
sort(x, x + n);
int a = (n + 1 ) / 2 - 1 ;
int ans = 0 ;
for ( int i = 0 ; i < n; i ++ )
ans += abs(y[a] - y[i]) + abs(x[a] - x[i]);
printf( " %d\n " , ans);
return 0 ;
}