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.  

 

posted @ 2015-06-05 09:35  PbTfcLx  阅读(637)  评论(0编辑  收藏  举报