首页 > 代码库 > [POJ 1390]Blocks
[POJ 1390]Blocks
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.
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
291 2 2 2 2 3 3 3 111
Sample Output
Case 1: 29Case 2: 1
Source
Liu Rujia@POJ
LRJ出的题果然诡异!这个DP很奇怪,因为状态很难确定,而且方块的状态难表示,可以将初始时各个颜色相同的方块合并,只关心这些大块的颜色和长度,若用f[i][j]表示将[i,j]区间的砖块合并的最大价值,找不到不同状态间的直接递推关系,所以要用f[i][j][len]表示合并[i,j],第j个后紧接着一个长为len的大块,有2种决策:把j和后面的len长大块合并,或者留下他们,找到前面[i,j]的另一个颜色相同的大块,三个一块消掉,这就把问题转换成递归式思想可以解决的问题,这里用记忆化DFS比较好写,不过一定要注意终止条件(DP的边界)——当这个方块的区间为1,即只有1个大块时,直接把这个大块和右边的相同颜色大块消除即可,还有要注意的是,题目有多组测试数据,每次要把记忆化数组清零!
#include <stdio.h>#include <string.h>#define MAXN 220struct box //盒子{ int color,len; //盒子的颜色、长度}segment[MAXN];int score[MAXN][MAXN][MAXN]; //s[l][r][extra_len]表示第l-r个大块,右边紧接着长度为extra_len,与第r个大块颜色相同的大块,合并操作后获得的分数int click_box(int l,int r,int extra_len) //获得第l-r个大块,右边紧接着长度为extra_len,与第r个大块颜色相同的大块,合并操作后获得的分数{ int result,i,temp; if(score[l][r][extra_len]) return score[l][r][extra_len]; result=extra_len+segment[r].len; result*=result; if(l==r) { score[l][r][extra_len]=result; return result; } result+=click_box(l,r-1,0); for(i=r-1;i>=l;i--) //遍历找到一个与第r个大块颜色相同,且操作后获得分值最大的大块 { if(segment[i].color!=segment[r].color) continue; temp=click_box(l,i,segment[r].len+extra_len)+click_box(i+1,r-1,0); if(temp<=result) continue;//结果不够优,跳过 result=temp; break; } score[l][r][extra_len]=result; return score[l][r][extra_len];}int main(){ int t,x,i,j,n,end,clr; scanf("%d",&t); for(x=1;x<=t;x++) { end=1; scanf("%d%d",&n,&segment[end].color); segment[end].len=1; for(i=2;i<=n;i++) { scanf("%d",&clr); if(clr==segment[end].color) segment[end].len++; //如果新的块与之前大块颜色一样,该大块的长度+1 else { segment[++end].color=clr; //否则新增一个大块 segment[end].len=1; } } printf("Case %d: %d\n",x,click_box(1,end,0)); memset(score,0,sizeof(score)); } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。