P2135 题解
题意:
给定
分析:
首先, 双倍积分 传送门。二者大同小异了,个人觉得按照链接里的题来看会更清晰易懂,所以我们接下来默认按输入转化成实际的序列,再进行操作。
观察题意,合并序列,加分,最大值,联想一下合并石子,是不是区间 DP 的样子就出来了。 但是我们发现,这题不能直接令
考虑枚举最后一个方块消掉的时候,假设我们当前的区间是
决策的过程就是要么直接删去该节点,要么就去找
本题真的很难,感性理解吧。
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<vector>
#include<string>
using namespace std;
int t,n,a[550],dp[550][550][100],dis[550];
int main(){
int cnt = 0;
scanf("%d",&cnt);
int b[cnt+5];
for(int i=1;i<=cnt;++i)scanf("%d",b+i);
for(int x,i=1;i<=cnt;++i){
scanf("%d",&x);
while(x--)a[++n]=b[i];
//转换一下
}
for(int i=n;i;--i)
for(int j=i+1;j<=n;++j)
if(a[i] == a[j])dis[i]++;//节点i右边有多少个颜色相同的预处理,其实就是第三维的状态上限
for(int i=n;i;--i)//倒叙O,因为是考虑后面带多少个同色的,从后往前来才行
for(int j=i;j<=n;++j){
for(int k=i;k<j;++k)
if(a[k] == a[j])//同色的点
for(int l = 0;l <= dis[k];++l)//转移
dp[i][j][l] = max(dp[i][j][l],dp[k+1][j-1][0] + dp[i][k][l+1]);//中间区间的贡献加上左边区间拼上l个同色的贡献
for(int p=0;p<=dis[j];++p)
dp[i][j][p] = max(dp[i][j][p],dp[i][j-1][0] + (p+1)*(p+1));//不考虑内部同色,直接带上右边同色的贡献
}
printf("%d\n",dp[1][n][0]);//区间1,n拼上0个同色就是最大值
}