POJ 1390
CH POJ1390
Description
Some of you may have played a game called ‘Blocks’. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Silver, Silver, Bronze, Bronze, Bronze, Gold.
The corresponding picture will be as shown below:
Figure 1
If some adjacent boxes are all of the same color, and both the box to its left(if it exists) and its right(if it exists) are of some other color, we call it a ‘box segment’. There are 4 box segments. That is: gold, silver, bronze, gold. There are 1, 4, 3, 1 box(es) in the segments respectively.
Every time, you can click a box, then the whole segment containing that box DISAPPEARS. If that segment is composed of k boxes, you will get k*k points. for example, if you click on a silver box, the silver segment disappears, you got 4 *4=16 points.
Now let’s look at the picture below:
Figure 2
The first one is OPTIMAL.
Find the highest score you can get, given an initial state of this game.
Input
The first line contains the number of tests t(1<=t<=15). Each case contains two lines. The first line contains an integer n(1<=n<=200), the number of boxes. The second line contains n integers, representing the colors of each box. The integers are in the range 1~n.
Output
For each test case, print the case number and the highest possible score.
Sample Input
2
9
1 2 2 2 2 3 3 3 1
1
1
Sample Output
Case 1: 29
Case 2: 1
Source
区间
,加状态参数。
如果只是用状态
来描述消去方块
到方块
获得的分数是无法形成递推关系的。
因为在这个时候对于最右边的大块有两种选择:
- 一是直接消去。
- 二是将其与左边某个大块合并删除。
而对于选择二来说,删去未必是最优方案,也许还应该与左边的某方块合并后消去。
所以只有两个参数是无法准确描述状态并形成递推关系的。
解决方案就是“加参数”
表示消去方块
,
同时
右边与
同色的方块长度(也称之为个数)为
此时递推关系:
- 直接消去
:
- 将
与左边某个方块
合并:
note:
在选择方块序号
时注意循环边界处理
——摘自林伏案
#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
struct Segment
{
int color,len;
Segment (int c,int l) : color(c), len(l) {};
Segment () {};
}seg[maxn];
int f[maxn][maxn][maxn];
int block[maxn];
inline int dp(int fr,int to,int len)
{
if (f[fr][to][len]!=-1)
return f[fr][to][len];
if (fr==to)
return f[fr][to][len]=(seg[to].len+len)*(seg[to].len+len);
int ans=dp(fr,to-1,0)+(seg[to].len+len)*(seg[to].len+len);
for (int i=fr; i<to; ++i)
if (seg[i].color==seg[to].color)
ans=max(ans,dp(i+1,to-1,0)+dp(fr,i,seg[to].len+len));
return f[fr][to][len]=ans;
}
int main()
{
int t,kase=0;read(t);
while (t--)
{
memset(f,-1,sizeof(f));
int n;read(n);
for (int i=1; i<=n; ++i)
read(block[i]);
int dep=0;
seg[dep]=Segment(block[1],1);
for (int i=2; i<=n; ++i)
if (block[i]==block[i-1]) ++seg[dep].len;
else seg[++dep]=Segment(block[i],1);
printf("Case %d: %d\n",++kase,dp(0,dep,0));
}
return 0;
}