Tower /点的移动(洛谷 1632)题解
【问题描述】
平面上有N个整数坐标点。如果将点(x0,y0)移动到(x1,y1),则需要的代价为|x0-x1|+|y0-y1|。求使得K(K=1,…,N)个点在同一位置上最少需要的代价。
【样例输入】
4
15 14
15 16
14 15
16 15
【样例输出】
0
2
3
4
【解题思路】
初看这道题,还以为是只能移动到有点的地方,即把别的点移动到一个点上,移动(k-1)个点所需要的最小代价,结果发现样例都过不去……接着分析了一下样例,发现样例是将k个点都移动到了(15,15)上去,当然,k=1的时候不需要移动,于是我就去找所有x,y的中位数,结果过了样例,但是OJ上为0分,那我们再重新来分析一下题目。
题目中是可以移到任意一个点的,我们不难发现这个点的x必定在所有x坐标之间,同理,y也如此,因此,我们只要枚举每一个x,y然后将每一个点都去移动一次,找出移动k个点的时候,最小的移动代价即可。
那么我们在这题中可以用一个三重循环,因为N的值并不大,只有50,三重循环并不会TLE。这里用三重循环的作用是方便计算每一个点移动的代价,详见代码。
【代码实现】
1 type rec=record 2 x,y:longint; 3 end; 4 var a:array[0..55] of rec; 5 f:array[0..55,0..55] of longint; 6 d,ans:array[0..55] of longint; 7 i,j,n,k,s:longint; 8 procedure sort(l,r:longint); 9 var i,j,x,y:longint; 10 begin 11 i:=l; 12 j:=r; 13 x:=d[(l+r) shr 1]; 14 repeat 15 while d[i]<x do 16 inc(i); 17 while x<d[j] do 18 dec(j); 19 if not(i>j) then 20 begin 21 y:=d[i]; 22 d[i]:=d[j]; 23 d[j]:=y; 24 inc(i); 25 j:=j-1; 26 end; 27 until i>j; 28 if l<j then 29 sort(l,j); 30 if i<r then 31 sort(i,r); 32 end; 33 begin 34 readln(n); 35 for i:=1 to n do 36 with a[i] do 37 readln(x,y); 38 for i:=1 to n do 39 ans[i]:=maxlongint; 40 for i:=1 to n do 41 for j:=1 to n do 42 begin 43 for k:=1 to n do 44 d[k]:=abs(a[k].x-a[i].x)+abs(a[k].y-a[j].y); //枚举每一个点移动到xi,yj上需要的代价。 45 sort(1,n); 46 s:=0; 47 for k:=1 to n do 48 begin 49 s:=s+d[k]; 50 if s<ans[k] then 51 ans[k]:=s; 52 end; //更新最优解 53 end; 54 for i:=1 to n do 55 writeln(ans[i]); 56 end.