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.  

 

你可能感兴趣的:(题解)