1. 程式人生 > >【洛谷P1889】士兵站隊

【洛谷P1889】士兵站隊

clu code 最終 兩種 algorithm 變形 .cn www 輸出

題目描述

在一個劃分成網格的操場上, 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

分析(轉載)

轉自http://www.cnblogs.com/bennettz/p/6486103.html

一 士兵有多種移動方式
通過適當的移動順序和移動路線可以使得同一時刻不會有兩名士兵站在同一點
二 題目要求最佳移動方式(即求移動的最少步數)
題目要求轉化為求士兵站立的“最終位置”,即如何取“最終位置”使得士兵移動的步數最少(最優)
Y軸方向上的考慮
設目標坐標為M,即n個士兵最終需要移動到的Y軸的坐標值為M
n個士兵的Y軸坐標分別為:
Y0,Y1,Y2 …… …… Yn-1
則最優步數S=|Y0-M|+|Y1-M|+|Y2-M|+ …… …… +|Yn-1-M|
結論:M取中間點的值使得S為最少(最優)
證明:……
從最上和最下的兩個士兵開始遞推……
最優位置
最優位置
歸結到最後,處於中間位置的士兵的Y軸坐標值就是“最終位置”的Y軸坐標
可能有兩種情況
士兵總數為雙數情況:取中間兩點間的任意一個位置
士兵總數為單數情況:取中間點的所在位置
解決辦法:對所有的Y軸坐標進行排序(O(nlogn))或者進行線性時間選擇(O(n))
然後取“中間”點的Y軸坐標值作為最佳位置M的值
最後通過公式求出Y軸方向上移動的最優步數
X軸方向上的考慮
首先需要對所有士兵的X軸坐標值進行排序
然後,按從左至右的順序依次移動到每個士兵所對應的“最終位置”(最優),所移動的步數總和就是X軸方向上需要移動的步數
例,最左的士兵移動到“最終位置”的最左那位,第二個士兵移動到“最終位置”的第二位
則總的步數為:士兵一移動步數+士兵二移動步數+ …… +士兵n移動步數
如何確定X軸方向上的最佳的“最終位置”?
共n個士兵
他們相應的X軸坐標為:X0,X1,X2 …… …… Xn-1
設,士兵需要移動到的“最終位置”的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|
註意到公式的形式與Y軸方向上的考慮一樣,同樣是n個已知數分別減去一個待定數後取絕對值,然後求和
因此還是采用取中位數的辦法求得k值,最後算出最優解

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=10000+5;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1; ch=getchar();}
    while(ch>=
0&&ch<=9){x=x*10+ch-0; ch=getchar();} return x*f; } int n,ans; int x[maxn],y[maxn]; int main() { n=read(); for(int i=1;i<=n;i++) x[i]=read(),y[i]=read(); sort(x+1,x+n+1); sort(y+1,y+n+1); for(int i=1;i<=n;i++) x[i]-=i; sort(x+1,x+n+1); int mid=(n+1)>>1; for(int i=1;i<=n;i++) ans+=abs(x[i]-x[mid])+abs(y[i]-y[mid]); printf("%d\n",ans); return 0; }

【洛谷P1889】士兵站隊