每日小小的打卡
这是一道区间dp问题,读完题目,很容易想到要断环成链,设$f[i][j]$为i 到 j的值最高分,不难发现如下状态方程:
$f[i][j] = max(f[i][k] + f[k][j])$
$f[i][j] = max(f[i][k] × f[k][j])$
仔细考虑,加法这样做是没有问题的,但是减法的话,由于负数,会出现一下错误
我们可以再用一共$g[i][j]$来维护最小值
加法还是一样的:
$g[i][j] = min(g[i][k] + g[k + 1][j])$
然而对于乘法,很明显有四个组合:
1.lmax*rmax
2.lmax*rmin
3.lmin*rmin
4.lmin*rmin
max = max(1,2,3,4),min = min(1,2,3,4)
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
const int INF = 0x3f3f3f3f;
int a[N];
char c[N];
int n;
int f[N][N], g[N][N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> c[i] >> a[i];
c[n + i] = c[i];
a[n + i] = a[i];
}
memset(f, -0x3f, sizeof f);
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= (n << 1); i++) {
f[i][i] = g[i][i] = a[i];
}
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= (n << 1); i++) {
int j = i + len - 1;
for (int k = i; k < j; k++) {
if (c[k + 1] == 't') {
f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j]);
g[i][j] = min(g[i][j], g[i][k] + g[k + 1][j]);
} else {
int vals[4] = {
f[i][k] * f[k + 1][j],
f[i][k] * g[k + 1][j],
g[i][k] * f[k + 1][j],
g[i][k] * g[k + 1][j]
};
for (int t = 0; t < 4; t++) {
f[i][j] = max(f[i][j], vals[t]);
g[i][j] = min(g[i][j], vals[t]);
}
}
}
}
}
int ans = -INF;
int first_edges[N], cnt = 0;
for (int i = 1; i <= n; i++) {
int result = f[i][i + n - 1];
if (result > ans) {
ans = result;
cnt = 0;
first_edges[cnt++] = i;
} else if (result == ans) {
first_edges[cnt++] = i;
}
}
cout << ans << endl;
for (int i = 0; i < cnt; i++) {
if (i > 0) cout << " ";
cout << first_edges[i];
}
cout << endl;
return 0;
}

浙公网安备 33010602011771号