poj 1390 动态规划
题意:黑书P123 有一款方块消除的游戏,游戏规则如下:n个带颜色方块排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域)。游戏时,你可以任选一个区域消去。设这个区域包含的方块数为x,则将得到x^2个分值。方块消去之后,其右边的所有方块就会向左移动,与被消去方块的左边相连。求游戏的最大得分。
分析:题目的方块可以表示成color[i], len[i], 1 <= i <= l,其中l表示有多少段不同的颜色方块。color[i]表示第i 段的颜色,len[i]表示第i 段的方块长度。
设dp[i, j, k]表示把(color[i], len[i]) , (color[i+1], len[i+1]), ……, (color[j], len[j] + k)合并的最大得分。
考虑(color[j], len[j] + k)这一段,
1.马上消掉,dp[i, j-1, 0] + (len[j] + k) ^ 2;
2.和前面的若干段一起消,可以假设这若干段中最后面得那一段是p,则此时的得分是dp[i, p, len[j]+k] + dp[p+1, j-1, 0].
于是有 dp[i, j, k] = max(f[i, j-1, 0] + (len[j] + k) ^ 2, dp[ i, p, len[j]+k ] + dp[p+1, j-1, 0]),其中color[p] == color[r];
const int M = 200; int color[205], len[205]; int dp[M][M][M]; int pos; void readData(){ int n; cin>>n; memset(len, 0, sizeof(len)); memset(dp, 0, sizeof(dp)); pos=0; while(n--){ int a;cin>>a; if(a==color[pos]) len[pos]++; else { color[++pos] = a; len[pos]++; } } } int d(int i, int j, int k){ if( dp[i][j][k] ) return dp[i][j][k]; if(i-j==1 && k==0) return 0; dp[i][j][k] = d(i,j-1,0) + (len[j]+k) * (len[j]+k); FOR(p, i, j) if(color[p]==color[j]) { int t = d(i,p,k+len[j]) + d(p+1,j-1,0); checkmax(dp[i][j][k], t); } return dp[i][j][k]; } int main(){ int t; cin>>t; FOE(r, 1, t){ readData(); cout<<"Case "<<r<<": "<<d(1, pos, 0)<<endl; } return 0; }