poj1390 Blocks(经典区间dp/消除问题)

题目

poj1390 Blocks(经典区间dp/消除问题)_第1张图片

T(T<=15)组样例,每次给出n(n<=200)个方块,第i个整数ci代表方块的颜色(1<=ci<=n),

每次你可以手动消除一段连续的长度为x的方块,并获得这段方块带来的价值x^{2}

消除之后,后面的方块会跟上来,但并不会产生消除的连锁反应,需要你指定才会发生消除

求消完所有方块后的最大价值之和

思路来源

https://www.cnblogs.com/Tieechal/p/11637638.html 清楚明白的讲解

题解

经典区间dp消除问题的例题,也是入坑消除问题的第一道题,定义的状态很神奇

[Luogu2135] 方块消除,UVA10559 Blocks,一道题出了三遍

方块消除不用尺取把相同颜色的合在一起,而Blocks需要

 

dp[l][r]并不能解决问题,因为可能先消r后面的一段,使和r相同的颜色紧挨着r,这样的决策,使得dp[l][r]不能固定下来

因此多开一维,dp[l][r][lx]代表对于[l,r]区间,当前有lx个方块和b[r]颜色相同,紧跟在r后面没有被消除

 

本次决策有两种,决策是基于r这种颜色的,

一种是本次利用r的价值,把(lx+b[r])个消掉,递归到dp[l][r-1][0]的情形,

另一种为了以后更大的r的价值,是从[l,r-1]中找到一个和r颜色相同的位置i,先消掉[i,r-1]这段,从而把(lx+b[r])个续到i后面去

代码

#include
#include
#include
using namespace std;
const int N=205;
int t,n,m,a[N],b[N],v[N],dp[N][N][N];
int dfs(int l,int r,int lx){
	int &ans=dp[l][r][lx];
	if(~ans)return ans;
	int all=b[r]+lx;
	if(l==r){
		return ans=all*all;
	}
	ans=0;
	ans=max(ans,dfs(l,r-1,0)+all*all);
	for(int i=l;i

 

你可能感兴趣的:(#,区间dp,区间dp,消除问题)