[ybtoj5.2.3/UVA10559] 方块消除 Blocks [区间DP]

题意

给你 N N N 个数 ( N ⩽ 200 ) (N\leqslant 200) (N200) ,每次可以通过消去其中连续且相同的 x x x 个数以获得 x 2 x^2 x2 的分数
求可以获得的最大的分数

思路

一个很naive的想法就是设为 f i , j f_{i,j} fi,j 这种标准形式的区间DP

但想一下就会发现在里面的数会受到其他数的影响,所以这样是不可取的

那可不可以增加状态来表示呢?

f i , j , k f_{i,j,k} fi,j,k 表示区间 i i i j j j 且之后跟着 k k k 个与第 j j j 个数相同的数字

首先可以考虑直接消去后 k + 1 k+1 k+1 个,即

f i , j , k = f i , j − 1 , 0 + ( k + 1 ) 2 f_{i,j,k}=f_{i,j-1,0}+(k+1)^2 fi,j,k=fi,j1,0+(k+1)2

然后在考虑删去一个跟末尾数字一样的数与末尾一串数之间的所有数,可得

f i , j , k = max ⁡ a l = a j , i ⩽ l ⩽ j ( f i , l , k + 1 + f l + 1 , r − 1 , 0 ) f_{i,j,k}=\max\limits_{a_l=a_j,i\leqslant l\leqslant j}(f_{i,l,k+1}+f_{l+1,r-1,0}) fi,j,k=al=aj,iljmax(fi,l,k+1+fl+1,r1,0)

然后就可以DP了

代码

用记忆化实现的(似乎直接递推的话不好弄?)

#include<bits/stdc++.h>
#define N 210
using namespace std;
int f[N][N][N],nxt[N],head[N],n,T;
int dfs(int l,int r,int x)
{
	if(l>r)return 0;
	if(f[l][r][x])return f[l][r][x];
	f[l][r][x]=dfs(l,r-1,0)+(x+1)*(x+1);
	for(int i=nxt[r];i>=l;i=nxt[i])
		f[l][r][x]=max(f[l][r][x],dfs(l,i,x+1)+dfs(i+1,r-1,0));
	return f[l][r][x];
}
int main()
{
	int x;
	cin>>T;
	for(int t=1;t<=T;t++)
	{
		memset(head,0,sizeof(head));
		memset(nxt,0,sizeof(nxt));
		memset(f,0,sizeof(f));
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			nxt[i]=head[x];
			head[x]=i;
		}
		printf("Case %d: %d\n",t,dfs(1,n,0));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值