1. 程式人生 > >【P1889】SOLDIERS (中位數)

【P1889】SOLDIERS (中位數)

題目描述

在一個劃分成網格的操場上, n個士兵散亂地站在網格點上。由整數 座標 (x,y) 表示。士兵們可以沿網格邊上、下左右移動一步,但在同時刻任一網格點上只能有名士兵。按照軍官的命令,們要整齊地列成個水平佇列,即排成 佇列,即排成 (x,y),(x+1,y), …,(x+n -1,y) 。如何選擇 x 和y的值才能使 士兵們以最少的總移動步數排成一列。

輸入輸出格式

輸入格式:

檔案的第 1 行是士兵數 n,1≤n≤10000 。接下來 n 行是士兵的初始位置, 每行 2 個整數 x 和y,-10000 ≤x,y≤10000 。

輸出格式:

檔案中 只有一個整 數是士兵排成一行需要的最少移動步。

輸入輸出樣例

輸入樣例1:
5
1 2
2 2
1 3
3 -2
3 3
輸出樣例1:
8
輸入樣例2:

   7
   2 3
   3 4
   4 5
   1 10
   5 21
   3 12
   10 5

輸出樣例2:
37

 
   
解析:
中位數的拓展題,需要從橫縱座標兩邊考慮,但是這個橫縱好像不是我理解的那種......
為了使座標形成(x,y),(x+1,y),(x+2,y)......(x+n-1,y),就可以使每個Xi
都向左移i個單位,在最理想的狀態下每個(Xi-i)就應該在同一個位置。然後我們需要思考:沒有達到同一個位置怎麼辦?顯然就應該取一個值使所有X值都向它移,於是中位數自然而然又出來了!
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int ans=0,n,x[10005],y[10005];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf(
"%d%d",&x[i],&y[i]); } sort(x+1,x+n+1); sort(y+1,y+n+1); int mid1=y[(n+1)/2]; for(int i=1;i<=n;i++) { x[i]-=i; } sort(x+1,x+n+1); int mid2=x[(n+1)/2]; for(int i=1;i<=n;i++) { ans+=abs(mid1-y[i]); ans+=abs(mid2-x[i]); } printf("%d",ans); }