士兵站隊問題
題目描述 description
在乙個劃分成網格的操場上,n個士兵散亂地站在網格點上。網格點用整數座標(x,y)表示。士兵們可以沿網格邊往上、下、左、右移動一步,但在同一時刻任一網格點上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成乙個水平佇列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何選擇x和y的值才能使士兵們以最少的總移動步數排成一行。程式設計計算使所有士兵排成一行需要的最少移動步數。
輸入描述 input description
第1行是士兵數n,1≤n≤10000。接下來n行是士兵的初始位置,每行有2個整數x和y,-10000≤x,y≤10000。
輸出描述 output description
乙個資料,即士兵排成一行需要的最少移動步數。
樣例輸入 sample input
1 22 2
1 33 -2
3 3樣例輸出 sample output
資料範圍及提示 data size & hint
-10000≤x,y≤10000
**如下:
#include
#include
#include
#include
#include
using namespace std;
int x[10009],y[10009];
int main()
{int n,sx=0,sy=0;
scanf("%d",&n);
for(int i=0;i思路解析:
士兵站隊,要站在同一排,且乙個點只有乙個士兵。
士兵要先統一y軸,即士兵移動後縱座標相等,然後移動x軸使其分散開;
一、統一y軸的最優方法
設目標座標為m,即n個士兵最終需要移動到的y軸的座標值為m
n個士兵的y軸座標分別為:
y0,y1,y2 …… …… yn-1
則最優步數s=|y0-m|+|y1-m|+|y2-m|+ …… …… +|yn-1-m|;
那麼m取何數值時,會發現當m為縱座標排序後的中位數時s最小。接下來給予證明
|a|-|b|≤|a+(或者是相減)b|≤|a+b|≤|a|+|b|(不做證明了)
例如(假設有兩個士兵,我們從簡單的開始討論)
則 s=|y0-m|+|y1-m|,可轉換為 s=|m-y0|+|y1-m|;
兩個絕對值相加,我們可以用開始的公式消去m;
則 |m-y0|+|y1-m| ≥ |y1-y0|;
那麼何時 |m-y0|+|y1-m| = |y1-y0|取得最小呢?
可發現 當絕對值號中符號相同時 可取得最小,令其都大於0
則 y0可想 當m在兩個士兵縱座標之間時 無論怎麼移動 兩個士兵移動的距離和 都是兩個士兵之間的距離
所以s=|y0-m|+|y1-m|+|y2-m|+ …… …… +|yn-1-m|對於這個公式使前一半絕對值號內交換位置,都令其大於零,消去m,最後會發現m就是士兵排序之後縱座標的中位數
二、同統一y軸的方法
設,士兵需要移動到的「最終位置」的x軸座標值為:k,k+1,k+2 …… …… k+(n-1)
則所求最優步數s=|x0-k|+|x1- (k+1) |+|x2-(k+2)|+ …… +|xn-1-(k+(n-1))|
經過變形s=|x0-k|+|(x1-1)-k|+|(x2-2)-k|+ …… …… +|(xn-1-(n-1))-k|
k的取值同理是其中位數;
注意:x軸先從小到大排序之後,在依次減0-- n-1,再排序,再找中位數。
士兵站隊問題
問題描述 在乙個劃分成網格的操場上,n個士兵散亂地站在網格點上,網格點由整數座標 x,y 表示。士兵們可以沿網格邊上 下 左 右移動一步,但在同一時刻任一網點上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成乙個水平佇列,即排列成 x,y x 1,y x n,y 如何選擇x和y的值才能使士兵們以最...
士兵站隊問題
題解 首先已知縱向移動可以直接通過求中位數得到 那麼問題就是橫方向移動了 我們假設第一位士兵站的位置是k,因為x從x1開始,那麼我們假設成起始位置為k 1吧 不懂接著看完你就懂了 那麼 第二位士兵的位置是 k 2,接著是k 3,k 4,k n 所以,士兵橫向 即平行於y軸方向 移動的距離為 x1 k...
9209 士兵站隊問題
time limit 10 second memory limit 2 mb 問題描述 在乙個劃分成網格的操場上,n個士兵散亂地站在網格點上。網格點由整數座標 x,y 表示。士兵們可以沿網格邊上 下 左 右移動一步,但在同一時刻任一網格點上只能有一名士兵。按照軍官的命令,士兵們要整齊地列成乙個水平佇...