码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1390 BLOCK

时间:2017-07-01 23:24:18      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:class   last   exist   优化   mem   round   时间   没有   call   

 

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

时间限制:5000ms 空间限制:65536K
 
  题目大意:给定n个箱子及其颜色,颜色相同的k个盒子可以消除,得分k*k,求最大得分(盒子消除后右边的盒子自动往左移)。
 
  lrj大神书上的题目,很经典的区间DP。
 
  首先我们可以先对题目给出的条件进行优化,把k个颜色相同且连在一起的盒子合并成一个新的盒子,颜色不变,记录其盒子个数num[i]。
 
  因为二维的状态s[i][j]无法把区间联系起来即没有利用到盒子消除后往左移动的性质,所以增加一维k--s[i][j][k],表示合并区间[i,j]并把盒子j右
边k个与盒子j的颜色相同的盒子消除最大得分。
  对于 s[i][j][k]有两种转移:
一、单独消除  s[i][j][k]=s[i][j-1][0]+(num[j]+k)^2
二、与中间某个颜色与盒子j相同颜色的盒子p消除 s[i][j][k]=s[i][p][k+num[j]]+s[p+1][j-1][0]
  最后答案为s[1][n][0]
  这题我写的是记忆化搜索,常规写法可能会稍微麻烦一点
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define R register
 5 
 6 int T,n,last[201],color[201],pre[201],num[201],s[201][201][201];
 7 
 8 void memorysearch(int l,int r,int k){
 9   if (s[l][r][k]||r<l) return;
10   if (l==r){
11       s[l][r][k]=(num[l]+k)*(num[l]+k);
12       return;
13   }
14   memorysearch(l,r-1,0);
15   s[l][r][k]=s[l][r-1][0]+(num[r]+k)*(num[r]+k);
16   for (R int p=pre[r];p>=l;p=pre[p]){
17        memorysearch(l,p,k+num[r]);
18        memorysearch(p+1,r-1,0);
19        s[l][r][k]=std::max(s[l][r][k],s[l][p][k+num[r]]+s[p+1][r-1][0]);
20   }
21 }
22 
23 int main(){
24   scanf("%d",&T);
25   for (R int round=1;round<=T;++round){    
26     memset(s,0,sizeof s);n=0;
27       memset(pre,0,sizeof pre);
28     memset(last,0,sizeof last);
29       int size;scanf("%d",&size);
30       for (R int i=1;i<=size;++i){
31         int c;scanf("%d",&c);
32         if (c==color[n]) ++num[n];
33         else color[++n]=c,num[n]=1;
34     }
35     for (R int i=1;i<=n;++i) pre[i]=last[color[i]],last[color[i]]=i;
36     memorysearch(1,n,0);
37     printf("Case %d: %d\n",round,s[1][n][0]);
38   }
39   return 0;
40 }

 评测地址:http://poj.org/problem?id=1390

POJ 1390 BLOCK

标签:class   last   exist   优化   mem   round   时间   没有   call   

原文地址:http://www.cnblogs.com/hyheng/p/7103652.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!