区间dp问题
有n个集合,第i个集合记为Si,集合按环状排列,即第i+1个集合右边是第ii个集合,第n个集合右边是第ii个集合。
一开始每个集合里只有一个数,每次你可以选择两个相邻的集合S,T然后合并成S∪T,之后你可以获得收益|S|×|T|,其中|S|表示集合S的元素个数。
你需要一直进行以上的操作直到只剩一个集合为止,求能获得的最大的收益之和。
断环为链,复制两倍区间DP。
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int a[N];
int sum[N][N];
int f[N][N];
bitset<N> cnt;
signed main() {
int n;
cin >> n;
for (register int i = 1; i <= n; ++i) cin >> a[i];
for (register int i = 1; i <= n; ++i) a[i + n] = a[i];
for (register int len = 1; len <= n; ++len) {
for (register int l = 1, r = len + l - 1; r <= 2 * n; ++l, ++r) {
cnt.reset();//初始化置为0
for (register int i = l; i <= r; ++i) cnt[a[i]] = 1;
sum[l][r] = cnt.count();
// cerr << l << " " << r << " " << sum[l][r] << endl;
}
}
for (register int len = 2; len <= n; ++len) {
for (register int l = 1, r = l + len - 1; r <= 2 * n; ++l, ++r) {
for (register int k = l; k < r; ++k) {
f[l][r] = max(f[l][r], f[l][k] + f[k + 1][r] + sum[l][k] * sum[k + 1][r]);
}
}
}
int ans = 0;
for (register int i = 1; i <= n; ++i) ans = max(ans, f[i][i + n - 1]);
cerr << ans << endl;
}