poj 1390(消除方块(blocks))
今天中午从黑书上看到了的一道例题,动态规划——>线性模型的例1题。
看书都看不懂!
后面还是看了网上的题解,才渐渐明白......
估计我也说不清楚,所以尽力好了。
样例:
1 2 2 2 2 3 3 3 1
我们建立两个数组 :color, num.
其中,color储存的是颜色值,Num是相同颜色的个数。
例如,对上面的样例来说,我们就有:color[1..4]:=(1,2,3,1). num[1..4]:=(1,4,3,1).
我是看结题报告才懂的。所以觉得如果我没看题解,我实在是想不出这种状态来。
f[i,j,k]表示合并第i到第j组色块所得到的最大分,至于这个k,他其实是第j组之后的某一个和j组的color值相等的组的长度,现在可能说不清,慢慢讲清吧。
该状态有两种决策方式:
1.直接合并第j组,再合并i到j-1组。 此时f[i,j,k]:=f[i,j-1,0]+(num[j]+k)^2.(这个又出现了,为什么会有这个K,他是在上一层递归中加入进来的,继续看下面可能就明白了)。
2.不直接合并而是在i 和j-1 中找到某一组,并且该组的颜色与第j组颜色相同,设为p,先将p+1到j-1组合并,然后p和j因为颜色相同,自然就合成为一组了,假设合并的组还是p。
此时p的长度就为(num[p]+num[j])了,k的作用就在于此:
f[i,j,k]:=f[i,p,k+num[j]]+f[p+1,j-1,0].
为什么k会变成k+num[j]呢? 看下图:

如: 先合并 7,8,9,再合并 5,6,10,11,我们可以等效为第二张图,把5,6,10,11看成整体,由于该整体的num值不再为前者的num值,我们需要一个附加值来表示当前的num,这个附加的num就是k,显然k为当前附加值再加上等效后所需要的附加值,在这里k为2.
所以,方程就的出来了!
f[i,j,k]:=max(f[i,j-1,0]+(num[j]+k)^2,f[i,p,k+num[j]]+f[p+1,j-1,0])。(其中i<=p<j 并且 color[p]=color[j]).
answer:=f[1,n,0].
接下来就很好办了.
代码:
1 program p1390; //uses math;
2 {var
3 i,n:longint;
4 =================================================
5 procedure mainn;}
6 var
7 i,j,k,l,m,q,m2,n,n2:longint;
8 color,num,s:array[0..200]of longint;
9 f:array[0..200,0..200,0..200]of longint;
10 function max(a,b:longint):longint;
11 begin
12 if a>b then exit(a)
13 else exit(b);
14 end;
15 function haha(l,r,k:longint):longint;
16 var
17 i,j,m,n,p:longint;
18 begin
19 if f[l,r,k]<>0 then exit(f[l,r,k]);
20 if l=r then exit((num[r]+k)*(num[r]+k));
21 f[l,r,k]:=haha(l,r-1,0)+(num[r]+k)*(num[r]+k);
22 for i:=l to r-1 do
23 begin
24 if color[i]=color[r] then
25 begin
26 f[l,r,k]:=max(f[l,r,k],haha(l,i,num[r]+k)+haha(i+1,r-1,0));
27 end;
28 end;
29 haha:=f[l,r,k];
30 end;
31 begin
32 assign(input,'p1390.in');
33 reset(input);
34 assign(output,'haha.out');
35 rewrite(output);
36 read(n2);
37 for q:=1 to n2 do
38 begin
39 fillchar(s,sizeof(s),0);
40 fillchar(f,sizeof(f),0);
41 fillchar(num,sizeof(num),0);
42 fillchar(color,sizeof(color),0);
43 read(n);
44 j:=0;
45 for i:=1 to n do
46 read(s[i]);
47 i:=1;
48 while i<=n do
49 begin
50 m:=s[i];
51 inc(j);
52 color[j]:=s[i];
53 while color[j]=s[i] do
54 begin
55 inc(i);
56 inc(num[j]);
57 end;
58 end;
59 writeln('Case ',q,': ',haha(1,j,0));
60 end;
61 close(input);
62 close(output);
63 end.
64 {==============================================}
65 {begin
66 readln(n);
67 for i:=1 to n do
68 mainn;
69 end.}

浙公网安备 33010602011771号