方法:记忆化搜索
我们定义
d
p
[
l
]
[
r
]
[
x
]
dp[l][r][x]
dp[l][r][x] 代表在区间
[
l
,
r
]
[l,r]
[l,r],且
r
r
r 右侧拥有
x
x
x 个与右端点颜色相同的点的情况下所能得到的最优解。
- 若 l = r ,此时 d p [ l ] [ r ] [ x ] dp[l][r][x] dp[l][r][x] 的结果为 ( x + 1 ) 2 (x+1)^2 (x+1)2
- 若 l < r,先直接消去右端点,结果 d p [ l ] [ r ] [ x ] = d p [ l ] [ r − 1 ] [ 0 ] + ( x + 1 ) 2 dp[l][r][x]=dp[l][r-1][0]+(x+1)^2 dp[l][r][x]=dp[l][r−1][0]+(x+1)2,然后比较从中间断开,若存在 l < = i < r l<=i<r l<=i<r,且 a [ i ] = a [ r ] a[i]=a[r] a[i]=a[r],即 i i i点颜色和 r r r点颜色相同,将区间分为 [ l , i ] [l,i] [l,i]和 [ i + 1 , r − 1 ] [i+1,r-1] [i+1,r−1]和 [ r , r ] [r,r] [r,r]三部分,先消掉 [ i + 1 , r − 1 ] [i+1,r-1] [i+1,r−1],再合并 [ l , i ] [ r , r ] [l,i][r,r] [l,i][r,r],结果为 d p [ l ] [ i ] [ x + 1 ] + d p [ i + 1 ] [ r − 1 ] [ 0 ] dp[l][i][x+1]+dp[i+1][r-1][0] dp[l][i][x+1]+dp[i+1][r−1][0]
最终答案为 d p [ 0 ] [ n − 1 ] [ 0 ] dp[0][n-1][0] dp[0][n−1][0]
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 1e2 + 10;
const int mod = 1e9 + 7;
int n;
int a[maxn];
LL dp[maxn][maxn][maxn];
LL dfs(int l, int r, LL x) {
if (dp[l][r][x]) return dp[l][r][x];
if (l == r) return dp[l][r][x] = (x + 1) * (x + 1);
else if (l < r) {
dp[l][r][x] = dfs(l, r - 1, 0) + (x + 1) * (x + 1);
for (int i = l; i < r; i++) {
if (a[i] == a[r]) dp[l][r][x] = max(dp[l][r][x], dfs(l, i, x + 1) + dfs(i + 1, r - 1, 0));
}
return dp[l][r][x];
}
return 0;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
cout << dfs(0, n - 1, 0);
return 0;
}
学习自:千千的网站