2017.04.02【NOIP 普及組】模擬賽C組 T2:士兵
阿新 • • 發佈:2019-02-11
士兵
題目描述
在Gridland國家,有N個處於不同位置的士兵。該國上的地方都用兩個座標(X,Y)來表示。士兵能進行一次移動,每個士兵都可向上、向下、向左、或向右移動一個單位長,這樣他就能把自己的X或Y改變1或-1。
士兵們想進入一個水平線,彼此靠近,這樣他們的最後位置就是(X,Y)、(X+1,Y),…,(X+N,Y))。水平線上的士兵的最後順序以及整數X和Y,都是任意的。
現在目標是求如此配置士兵的最少移動數。
兩個或兩個以上的士兵在同一時間不處於同一位置。
輸入
輸入檔案soldiers.in的第一行含有一個整數N,1 <= N <=10000,N為士兵的數量。輸入檔案以後的N行應含有士兵的初始位置,對於每一個i, 1<= i <= N,輸入檔案的第I+1行含有兩個用空格分開的整數x[i],y[i],他們表示第I個士兵的座標,-10000<=x[i],y[i] <=10000.
輸出
輸出檔案soldiers.out僅有一行,它的值為使士兵移動到水平線彼此相鄰的最小移動次數。
樣例輸入
5
1 2
2 2
1 3
3 -2
3 3
樣例輸出
8
題解:
此題就是一個噁心的數學規律題。
題意說:士兵們想進入一個水平線,彼此靠近,這樣他們的最後位置就是(X,Y)、(X+1,Y),…,(X+N,Y))。那麼我們就會發現,士兵們合在一條水平線的位置,就是水平線的中間那條線。如圖:
紅色表示士兵。
中間的集合線是:
藍色標記的線最優。
於是乎,我們就把所有士兵給直接集合到此直線(不管重合),得到:
圖中兩個紅圈表示有兩個士兵。
他們集合到一條直線所需次數:6.
現在,用一個x來表示每個紅圈的x座標,再排序。如圖例得:
1 1 2 3 3
再因為士兵要緊密相連,所以最終佇列應為:
答案為6+2=8.
如何處理這一段???
我們就來看:x
1 1 2 3 3
排好隊最終的序號為:
1 2 3 4 5
再由想x[i]-i+1得:
1 0 0 0 -1
快排。
-1 0 0 0 1
從中間拓展,
於是搞搞就OK了。
標程:
type
new=array[1..10000] of longint;
var
a:array[1..10000] of longint;
b,z:array[-10000..10000] of longint;
x,y,x1,y1:array[1..10000] of longint;
i,j,k,l,n,m,sum,mid:longint;
procedure qs(l,r:longint;var a:new);
var
i,j,m,t:longint;
begin
i:=l;
j:=r;
m:=a[(l+r)div 2];
repeat
while a[i]<m do inc(i);
while a[j]>m do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then qs(l,j,a);
if i<r then qs(i,r,a);
end;
begin
assign(input,'soldiers.in');reset(input);
assign(output,'soldiers.out');rewrite(output);
readln(n);
for i:=1 to n do
begin
readln(x[i],y[i]);
end;
if n mod 2=1 then
mid:=(n+1) div 2
else
mid:=n div 2;
qs(1,n,y);
for i:=1 to n do
begin
sum:=sum+abs(y[i]-y[mid]);
end;
qs(1,n,x);
for i:=1 to n do
begin
x[i]:=x[i]-i+1;
end;
qs(1,n,x);
for i:=1 to n do
begin
sum:=sum+abs(x[i]-x[mid]);
end;
writeln(sum);
close(input);close(output);
end.