小明在玩一个消除游戏。这个消除游戏有点特别。游戏中,你会得到 n 个一维排列的有各自颜色的砖块。
消除的时候,你有三种消除方案。你可以单消一个砖块,这样你可以得到 a 的得分;如果两个颜色一样的砖块在一起,你可以将这两个砖块一起消除获得 b 的得分;如果三个颜色一样的砖块在一期,你可以将这三个砖块一起消除获得 c 的得分。
消除后,被消除的砖块自动消失,被消除砖块的左右两端的砖块将在消除之后挨在一起。
小明想知道在最优策略下他能得到多少得分。
第一行4个整数n,a,b,c,表示砖块数量,和一消/二消/三消的得分。
接下来一行个整数,第
个整数
表示第
个砖块的颜色。
输出最高得分
8 1 3 7 3 1 3 1 3 2 2 3
14
import java.util.Scanner;
// DP[i][j]:单消、双消、三消
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int a = in.nextInt(), b = in.nextInt(), c = in.nextInt();
int[] s = new int[n];
for (int i = 0; i < n; i++) {
s[i] = in.nextInt();
}
int[][] dp = new int[n][n];
for (int len = 1; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1, res = 0;
// 单消:枚举s[k]
for (int k = i; k <= j; k++) {
int l = (i <= k - 1) ? dp[i][k - 1] : 0; // s[i]还在
int r = (k + 1 <= j) ? dp[k + 1][j] : 0;
res = Math.max(res, a + l + r);
}
// 双消:枚举s[k]和s[i]匹配
for (int k = i + 1; k <= j; k++) {
if (s[k] != s[i]) continue;
int l = (i + 1 <= k - 1) ? dp[i + 1][k - 1] : 0; // s[i]没了
int r = (k + 1 <= j) ? dp[k + 1][j] : 0;
res = Math.max(res, b + l + r);
}
// 三消:枚举s[k]、s[t]和s[i]匹配
for (int k = i + 1; k < j; k++) {
if (s[k] != s[i]) continue;
for (int t = k + 1; t <= j; t++) {
if (s[t] != s[i]) continue;
int l = (i + 1 <= k - 1) ? dp[i + 1][k - 1] : 0;
int m = (k + 1 <= t - 1) ? dp[k + 1][t - 1] : 0;
int r = (t + 1 <= j) ? dp[t + 1][j] : 0;
res = Math.max(res, c + l + m + r);
}
}
dp[i][j] = res;
}
}
System.out.println(dp[0][n - 1]);
}
}