#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n, a, b, c;
cin >> n >> a >> b >> c;
vector<int> color(n);
for(int i = 0; i < n ; ++i){
cin >> color[i];
}
vector<vector<int>> dp(n, vector<int>(n, 0)); // dp[i][j]索引i到j的最大得分
// 初始化窗口为1
for(int i = 0; i < n; ++i){
dp[i][i] = a;
}
// 初始化窗口为2
for(int i = 0; i < n - 1; ++i){
int j = i + 1;
if(color[i] == color[j]){
dp[i][j] = max(2*a, b);
}else {
dp[i][j] = 2*a;
}
}
// 计算窗口>=3 的情况
for(int len = 3; len <= n; ++len){
for(int i = 0; i < n - len + 1; ++i){
int j = i + len - 1;
// 无条件拆分
for(int k = i; k < j; ++k){
dp[i][j] = max(dp[i][k] + dp[k + 1][j], dp[i][j]);
}
// 有条件拆分:相同颜色色块可合并拆分
for(int k = i + 1; k < j; ++k){
if(color[i] == color[j]){ // 区间两端颜色相同
if(color[k] == color[i]){
// 三色相同
dp[i][j] = max(dp[i][j], dp[i + 1][k - 1] + dp[k + 1][j - 1] + max({3*a, a + b, c}));
}else {
dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + max(2*a, b));
}
}else { // 区间两端颜色不同
if(color[k] == color[i]){
dp[i][j] = max(dp[i][j], dp[i + 1][ k - 1] + max(2*a, b) + dp[k + 1][j]);
}
if(color[k] == color[j]){
dp[i][j] = max(dp[i][j], dp[i][k - 1] +max(2*a, b) + dp[k + 1][j - 1]);
}
}
}
}
}
cout << dp[0][n - 1] << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
一、解题思路
1、人话版:当你知道由一个方块组成区间的奖励最大值,你就能算出由两个方块组成区间的奖励最大值,聪明的你,开始以此类推……
dp[i][j]含:消除 索引i到索引j位置的色块 可以获得的最大分值。
(1)单独消除每个方块的值固定 dp[i][i] = a;
(2)俩俩一组,看看一块杀俩分值大,还是一个一个杀分值大 (具体看游戏设计师的脑回路了,万一连续消除两个不给你分呢~)
(3)三个及以上一组,例如四个方块可以分成(1 + 3,2 + 2, 3 + 1)组合:
无条件遍历:别管有没有相同色块,咱就按顺序硬消
有条件遍历:先把端点中间多余的方块杀喽,再把端点处相同色块凑一起杀。
2、思想总结:从小区间的最优解,递推更大区间的最优解,无条件拆分(不合并相同颜色方块) + 有条件拆分(合并相同颜色方块)
3、备注:最开始我还初始化了窗口大小为三的情况:
// 初始化窗口为3
for(int i = 0; i < n - 2; ++i){
int j = i + 2;
if(color[i] == color[j] && color[i] == color[i + 1]){
// 三个同色
dp[i][j] = max({3*a, a + b, c});
}else if(color[i] == color[j]){
dp[i][j] = max(3*a, a + b);
}else{
// 拆成左一右二,或左二右一
dp[i][j] = max(dp[i][i] + dp[i + 1][j],dp[i][i + 1] + dp[j][j]);
}
}
后来发现这里的逻辑冗余,所以长度为3的时候,如 i = 0, k = 1, j = 2,出现类似于dp[i + 1][ k - 1] = dp[1][0] ,一维索引比二维索引大时初始值为0(但这么操作的话,dp初始值只能是0, 负值会影响结果),不会越界。

京公网安备 11010502036488号