poj1390 Blocks

来源:互联网 发布:h5 微信订餐系统源码 编辑:程序博客网 时间:2024/06/01 08:38

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.

如果直接区间dp的话,无法处理中间消掉把两块拼起来的情况。所以考虑增加维度。
用dp[i][j][k]表示从i..j一段,右边接上k个与a[j]颜色相同的块,得到的最大得分。
考虑a[j]什么时候被消掉,可能直接消掉,也可能消掉j左边一块之后和更左边的连起来消掉。
记a[j]同色的最多延伸到p,如果直接消掉,转移到dp[i][p-1][0]+(j-p+1+k)^2。
如果存在i<=q< p,a[q]=a[j],a[q]!=a[q+1]的话,还可以转移到dp[i][q][j-p+1+k]+dp[q+1][p-1][0]。
复杂度理论上限是O(n^4),但是因为很多状态达不到,很多q取不到,k也往往很小,采用记忆化搜索的话很快。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define DP dp[l][r][k]int dp[210][210][210],a[210],n;void init(){    int i;    memset(dp,-1,sizeof(dp));    scanf("%d",&n);    for (i=1;i<=n;i++)      scanf("%d",&a[i]);}int dfs(int l,int r,int k){    int i,j,x,y,z,p,q;    if (DP>=0) return DP;    p=r;    while (a[p-1]==a[r]&&p>l) p--;    if (p==l) return DP=(r-l+1+k)*(r-l+1+k);    DP=dfs(l,p-1,0)+(r-p+1+k)*(r-p+1+k);    for (i=p-1;i>=l;i--)      if (a[i]==a[r]&&a[i]!=a[i+1])        DP=max(DP,dfs(l,i,r-p+1+k)+dfs(i+1,p-1,0));    return DP;}int main(){    int T,K=0;    scanf("%d",&T);    while (T--)    {        init();        printf("Case %d: %d\n",++K,dfs(1,n,0));    }}
0 0