[ybtoj5.2.3/UVA10559] 方块消除 Blocks [区间DP]
题意
给你 N N N 个数 ( N ⩽ 200 ) (N\leqslant 200) (N⩽200) ,每次可以通过消去其中连续且相同的 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,j−1,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,i⩽l⩽jmax(fi,l,k+1+fl+1,r−1,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));
	}
}
                

                
            
        
浙公网安备 33010602011771号