1 条题解
-
1
考虑枚举最终的颜色 。
不难发现,每一段连续的位置只会出现两种情况:
- 直接被 覆盖。
- 先被区间最小值覆盖,再被 覆盖。
对两种情况分别使用区间 DP 即可。
#include <bits/stdc++.h> using namespace std; const int P = 1e9 + 7; long long d1[312][312], d2[312], d3[312]; int c[312], cc[312][312], cs[312], f[312]; int main() { int T; cin >> T; while (T--) { int n; cin >> n; long long ans = 0x3f3f3f3f3f3f3f3fll; for (int i = 1; i <= n; i++) { cin >> c[i]; cs[i] = cs[i - 1] + c[i]; cc[i][i] = c[i]; for (int j = 1; j <= i - 1; j++) cc[j][i] = min(cc[j][i - 1], c[i]); } memset(d1, 0, sizeof d1); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) { int mx = 1e9, mc = 0; long long sum = 0; for (int k = i; k <= j; k++) { sum += c[k]; if (c[k] < mx) mx = c[k], mc = 0; if (c[k] == mx) mc++; } d1[i][j] = mx * (sum - 1ll * mc * mx); } for (int i = 1; i <= n; i++) { memset(d2, 0x3f, sizeof d2); memset(d3, 0x3f, sizeof d3); memset(f, 0, sizeof f); for (int j = 1; j <= n; j++) { f[j] = f[j - 1]; if (c[i] == c[j]) f[j]++; } d2[0] = 0; for (int j = 0; j <= n - 1; j++) { for (int k = j + 1; k <= n; k++) { long long x; x = d2[j] + d1[j + 1][k] + 1ll * cc[j + 1][k] * c[i] * (k - j); d2[k] = min(d2[k], x); x = d3[j] + d1[j + 1][k] + 1ll * cc[j + 1][k] * c[i] * (k - j); d3[k] = min(d3[k], x); if (f[k] == f[j]) continue; x = d2[j] + 1ll * c[i] * (cs[k] - cs[j] - 1ll * c[i] * (f[k] - f[j])); d3[k] = min(d3[k], x); x = d3[j] + 1ll * c[i] * (cs[k] - cs[j] - 1ll * c[i] * (f[k] - f[j])); d3[k] = min(d3[k], x); } } ans = min(ans, d3[n]); } cout << ans << endl; } return 0; }
信息
- ID
- 135
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 6
- 已通过
- 1
- 上传者