(ssl2081)书本整理

书本整理

Description

小明的书架上放了很多书,为了使书架变得整洁,小明决定整理书架,他将所有书安高度大小排列,这样排了之后虽然整齐了许多,但小明发现,书本的宽度不同,导致书架看上去还是有些凌乱。小明将这个凌乱值定义为相邻两本书的宽度差的绝对值的和。
例如有4本书
1*2
5*3
2*4
3*1
小明将其排列整齐后的顺序是:
1*2
2*4
3*1
5*3
凌乱值为2+3+2=7。
于是小明决定拿掉其中的k本书,并使凌乱值最小。
已知每本书的高度都不一样。

Input

第一行两个数n和k,代表书的总数共有n 本,要求从中去掉k本书。(1=下面n行,每行两个整数值a和b,分别表示一本书的高度(a)和宽度(b),它们均小于200。

Output

一行一个整数,表示去掉k本书后,书架的最小凌乱值。

Sample Input

4 1
1 2
2 4
3 1
5 3

Sample Output

3

Hint

【数据范围】
30%的数据,n<=20。 100%的数据,n<=100,k

Source

题解:

   乍一看,本题像个石子合并,其实
又双叒叕是floyd,要求得出保留n-k(记为m)本书的最小凌乱值,f[i,j]表示放了i本书,最后一本为j的最小凌乱值
   首先按照题目要求来排序一下;接着初始化:在哪里只放一本书的凌乱值都为0;接着floyd即可
   注意!最优解不一定是f[m,n]!(万一最后一本书不是n,而是中间的任一一本呢?)所以我们要在f[m,1~n]中找最优解

动态规划方程为:

f[i,j]:=min(f[i-1,k]+abs(a[j,2]-a[k,2]),f[i,j]);
var
 a:array[0..100,1..2]of longint;
 f:array[1..100,1..100]of longint;
 n,m,k,i,j,ans:longint;
function min(a,b:longint):longint;
begin
 if a<b then exit(a);
 exit(b);
end;
begin
 read(n,k);
 m:=n-k;//最大放书数
 for i:=1 to n do read(a[i,1],a[i,2]);
 for i:=1 to n-1 do//这种数据选排就行啦
  for j:=i+1 to n do
   if a[j,1]<a[i,1] then begin a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0]; end;
 fillchar(f,sizeof(f),$7F);
 for i:=1 to n do f[1,i]:=0;//初始化
 for i:=2 to m do//一本书的情况已经在初始化的时候处理了~
  for j:=i to n do
   for k:=1 to j-1 do
    f[i,j]:=min(f[i-1,k]+abs(a[j,2]-a[k,2]),f[i,j]);
 ans:=23333333;
 for i:=1 to n do ans:=min(ans,f[m,i]);
 write(ans);
end.

猜你喜欢

转载自blog.csdn.net/ssl_lzx/article/details/80187769
SSL