博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[POJ 1390] Blocking
阅读量:4607 次
发布时间:2019-06-09

本文共 2832 字,大约阅读时间需要 9 分钟。

问题描述

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:

1602095-20190601115107260-1358187364.jpg

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 kk points. for example, if you click on a silver box, the silver segment disappears, you got 44=16 points.

Now let's look at the picture below:

1602095-20190601115114457-427385063.jpg

The first one is OPTIMAL.

Find the highest score you can get, given an initial state of this game.

输入格式

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.

输出格式

For each test case, print the case number and the highest possible score.

样例输入

2

9
1 2 2 2 2 3 3 3 1
1
1

样例输出

Case 1: 29

Case 2: 1

题意概括

给定一个序列,每次可以消去一个均为同种元素的区间,若区间长度为k,则将会获得k*k的分数。求最大可以获得的分数。

解析

显然这是一道区间动态规划的题目,可以用记忆化搜索的方式去实现。首先,我们可以用\(l\)\(r\)表示区间的范围。但是,仅由此还不够进行状态转移,因为还需要一个变量来衡量连续区间的长度。我们的突破口是每一个状态子区间的独立性。

对于一个子区间\([l,r]\),想要消去这个区间就只有两个办法:一是消去与r相邻的所有相同颜色的方块,再消去区间\([l,r-1]\);二是找到在\([l,r]\)中的某个位置\(k\)使\(r\)\(k\)颜色相同,消去区间\([k+1,r-1]\)使相同色块拼在一起后再一同消去,然后消去区间\([l,k-1]\)。这样做的依据就是前面提到的独立性。对于任何一个区间,目标都只是消去该区间,而不用管其他的区间。区间内部则由区间的相互独立的子区间决定。这就说明了下面的方程中0的出现。

综上所述,设\(f[l][r][k]\)表示在区间\([l,r]\)右边与\(r\)同色的有\(k\)块时消去该区间(包括右边相同的部分)的最优解。我们可以得到如下状态转移方程:

\[ f[l][r][k]=max(f[l][r-1][0]+(k+1)^2,f[l][i-1][k+1]+f[i+1][r-1][0]) \]
其中\(l<=i<=r,col[i]=col[r]\)。为了题目需要,我们还需要记录每个色块前面第一个和自己相同的颜色。这个可以借鉴图论中邻接表的思想来实现。

代码

#include 
#include
#include
#define N 202using namespace std;int t,n,i,a[N],f[N][N][N],nxt[N],head[N],cnt;int dp(int l,int r,int k){ if(l>r) return 0; if(f[l][r][k]!=0) return f[l][r][k]; f[l][r][k]=max(f[l][r][k],dp(l,r-1,0)+(k+1)*(k+1)); for(int i=nxt[r];i>=l;i=nxt[i]){ f[l][r][k]=max(f[l][r][k],dp(l,i,k+1)+dp(i+1,r-1,0)); } return f[l][r][k];}int main(){ cin>>t; while(t--){ cnt++; cin>>n; memset(f,0,sizeof(f)); memset(head,0,sizeof(head)); memset(nxt,0,sizeof(nxt)); for(i=1;i<=n;i++){ cin>>a[i]; nxt[i]=head[a[i]]; head[a[i]]=i; } cout<<"Case "<
<<": "<
<

转载于:https://www.cnblogs.com/LSlzf/p/10959081.html

你可能感兴趣的文章
Wireless Network 并查集
查看>>
51nod 1019 逆序数
查看>>
20145202马超《JAVA》预备作业1
查看>>
云推送注意(MSDN链接)
查看>>
OpenMobile's Application Compatibility Layer (ACL)
查看>>
竞价广告系统-广告检索
查看>>
强哥PHP面向对象学习笔记
查看>>
[转]基于.NET平台常用的框架整理
查看>>
Symbian (Read Inbox)读取收件箱的内容
查看>>
良好的编程规范
查看>>
struts2 入门
查看>>
.net 编译原理
查看>>
mean 快速开发和现有技术的对比分析
查看>>
Metro Style app :浏览器扩展
查看>>
linux的kernel是怎样工作的(TI_DM36X_ARM系统)(1)
查看>>
[luogu4310] 绝世好题 (递推)
查看>>
[luogu3203 HNOI2010] 弹飞绵羊 (分块)
查看>>
-Dmaven.multiModuleProjectDirectory system propery is not set.
查看>>
Python2 unichr() 函数
查看>>
Python 字典 copy()方法
查看>>