队伍排序

给定n个人的坐标,第一个人必须站在1 处,最后一个人站在L 处,其次让距离尽可能的相同。因此任意两个相邻的人相距必须与(L-1)/(n-1)【使用整数除法】相差最多为1,而且距离为(L-1)/(n-1)(整数除div)的个数尽可能的多,一个人由x移动到y的费用为|x-y|,求最小费用。

问题转化为给定线段和最优长度,在最优长度最多的前提下费用最小,进一步说,就是在一堆最优长度中插入剩余的所有1.

f[i,j]表示在前i个人就位后插入了j个(最优长度+1)的线段的最优解,DP方程直接看代码就行了,坐标式最好自己推导一下。

View Code
 1 program sunglasses(input,output);
2 var
3 x : array[0..2000] of longint;
4 f : array[0..2000,0..2000] of longint;
5 n,l : longint;
6 procedure init;
7 var
8 i : longint;
9 begin
10 readln(n,l);
11 for i:=1 to n do
12 readln(x[i]);
13 end; { init }
14 procedure swap(var aa,bb : longint );
15 var
16 tt : longint;
17 begin
18 tt:=aa;
19 aa:=bb;
20 bb:=tt;
21 end; { swap }
22 procedure sort(p,q : longint );
23 var
24 i,j,m : longint;
25 begin
26 i:=p;
27 j:=q;
28 m:=x[(i+j)>>1];
29 repeat
30 while x[i]<m do
31 inc(i);
32 while x[j]>m do
33 dec(j);
34 if i<=j then
35 begin
36 swap(x[i],x[j]);
37 inc(i);
38 dec(j);
39 end;
40 until i>j;
41 if i<q then sort(i,q);
42 if j>p then sort(p,j);
43 end; { sort }
44 function min(aa,bb :longint ):longint;
45 begin
46 if aa<bb then
47 exit(aa);
48 exit(bb);
49 end; { min }
50 procedure main;
51 var
52 i,j : longint;
53 step,last : longint;
54 begin
55 sort(1,n);
56 fillchar(f,sizeof(f),63);
57 f[1,0]:=abs(x[1]-1);
58 step:=(l-1) div (n-1);
59 last:=(l-1) mod (n-1);
60 for i:=2 to n do
61 for j:=0 to min(i-1,last) do
62 f[i,j]:=min(f[i-1,j],f[i-1,j-1])+abs(x[i]-(step*(i-1)+j+1));
63 writeln(f[n,last]);
64 end; { main }
65 begin
66 assign(input,'sunglasses.in');reset(input);
67 assign(output,'sunglasses.out');rewrite(output);
68 init;
69 main;
70 close(input);
71 close(output);
72 end.



原文地址:https://www.cnblogs.com/neverforget/p/2390364.html