经典的动态规划,LRJ神牛的书上经典例题第一题。
开一个三维数组,f[i][j][k]表示将i~j这一段,连上后面的k个格子全部消去所能够获得的最大价值。
状态转移方程:
f[i][j][k]=Max{
Max{f[i][p][len[j]+k]+f[p+1][j-1][0]}(color[p]=color[j] and i<p<j)//和前面某段一起消掉
f[i][j-1][0]+sqr(len[j]+k)//马上消掉这一段
}
其中,len[i]表示第i段连续区间的长度,比如说样例1中的len值分别为1,4,3,1
代码很简单:
Program POJ1390;//By_Thispoet Const maxn=200; Var i,j,k,m,n,l,r,p,o,q :Longint; f :Array[0..maxn,0..maxn,0..maxn]of Longint; len,color,maxr,rep :Array[1..maxn]of Longint; rpos :Array[1..maxn]of Integer; rec :Array[1..maxn,0..maxn]of Longint; Function Max(i,j:Longint):Longint; begin if i>j then exit(i);exit(j); end; BEGIN readln(o); q:=o; while o>0 do begin n:=0;l:=0; fillchar(rpos,sizeof(rpos),0); fillchar(rec,sizeof(rec),0); fillchar(len,sizeof(len),0); readln(r); for i:=1 to r do begin read(m); if l=m then inc(len[n]) else begin inc(n); inc(rec[m,0]);rec[m,rec[m,0]]:=n; rep[n]:=rec[m,0]; color[n]:=m;len[n]:=1; end; l:=m; end; for i:=n downto 1 do begin maxr[i]:=rpos[color[i]]; inc(rpos[color[i]],len[i]); end; //prepare fillchar(f,sizeof(f),0); for i:=1 to n do for k:=0 to maxr[i] do f[i,i,k]:=sqr(len[i]+k); for j:=1 to n-1 do for i:=1 to n-j do for k:=0 to maxr[i+j] do begin f[i,i+j,k]:=f[i,i+j-1,0]+sqr(len[i+j]+k); l:=rep[i+j]-1; while l>0 do begin p:=rec[color[i+j],l]; if p<i then break; f[i,i+j,k]:=Max(f[i,i+j,k],f[i,p,k+len[i+j]]+f[p+1,i+j-1,0]); dec(l); end; end; writeln('Case ',q-o+1,':',' ',f[1,n,0]); dec(o); end; END.