Description
Bsny的书架乱成一团了,帮他一下吧!
他的书架上一共有n本书,我们定义混乱值是连续相同高度书本的段数。例如,如果书的高度是30,30,31,31,32,那么混乱值为3;30,32,32,31的混乱值也为3。但是31,32,31,32,31的混乱值为5,这实在是太乱了。
Bsny想尽可能减少混乱值,但他有点累了,所以他决定最多取出k本书,再随意将它们放回到书架上。你能帮助他吗?
Data Constraint
20%的数据:1≤n≤20,k=1。
40%的数据:书的高度不是25就是32,高度种类最多2种。
100%的数据:1≤k≤n≤100,注意所有书本高度在[25,32]。
Solution
从数据范围上看,O(n3)的复杂度还是很优秀的,但是单靠三维转移无法完全把状态全都表示出来,我们要发现到高度的范围是[25,32],也就是只有8种,很容易就想到状态压缩。首先把连续一段合并在一起,设fi,j,k,l,表示当前做到第i块,已经让
我们大致可以分三种情况讨论,第一种:当前这一块不移动;当前块移动,但是在前面和后面都没有同样高度的书本(被取走视作不存在);第三种当前块移动,但是前面或后面有高度相同。对于每一种情况都转移一次。
Code
var
f:array[0..101,0..101,0..8,0..256] of longint;
a:array[0..101,1..2] of longint;
s:array[0..101] of longint;
p,bz:array[0..101] of boolean;
n,m,sum,tot,i,j,k,l,x,ans,allow:longint;
cas:boolean;
function min(x,y:longint):longint;
begin
if x<y then exit(x);exit(y);
end;
procedure change(var x,y:longint);
begin
if x>y then x:=y;
end;
begin
fillchar(a,sizeof(a),255);
readln(n,m);
for i:=1 to n do
begin
read(x); x:=x-24;
if x<>a[sum,1] then
begin
inc(sum);a[sum,1]:=x;a[sum,2]:=0;
end;
inc(a[sum,2]);
end;
n:=sum;
for i:=n downto 1 do if bz[a[i,1]] then p[i]:=true else bz[a[i,1]]:=true;
fillchar(f,sizeof(f),$7f);
allow:=f[0,0,0,0];f[0,0,0,0]:=0;
for i:=0 to n-1 do
for j:=0 to m do
for k:=0 to 8 do
for l:=0 to 255 do
if f[i,j,k,l]<>allow then
begin
sum:=f[i,j,k,l];
tot:=sum;if k<>a[i+1,1] then inc(tot);
change(f[i+1,j,a[i+1,1],l or(1 shl(a[i+1,1]-1))],tot);
if j+a[i+1,2]<=m then
begin
if (l and(1 shl(a[i+1,1]-1)))=(1 shl(a[i+1,1]-1)) then
change(f[i+1,j+a[i+1,2],k,l],sum);
if p[i+1] then
change(f[i+1,j+a[i+1,2],k,l],sum);
tot:=sum+1;
change(f[i+1,j+a[i+1,2],k,l],tot);
end;
end;
ans:=maxlongint;
for j:=0 to m do
for k:=0 to 8 do
for l:=0 to 255 do
ans:=min(ans,f[n,j,k,l]);
writeln(ans);
end.