UVA12836
\blue{\mathsf{Describe}}
给定长度为
然后,两两合并每个位置的度数,合并两个度数分别为
求合并代价总和的最小值。
\blue{\mathsf{Solution}}
首先,预处理出每个位置向两边的最长严格下降子序列的长度,这个用正反两遍 LIS 即可解决(甚至可以直接写
然后,就是经典的石子合并问题了。
用四边形不等式优化一下即可 AC。
\blue{\mathsf{Code}}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n;
int f[1005], g[1005];
ll b[1005], a[1005];
ll F[1005][1005], m[1005][1005];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin >> tt;
for (int zeq = 1; zeq <= tt; ++zeq) {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i <= n; ++i) f[i] = g[i] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) if (a[j] < a[i]) f[i] = max(f[i], f[j] + 1);
}
for (int i = n; i; --i) {
for (int j = n; j > i; --j) if (a[j] < a[i]) g[i] = max(g[i], g[j] + 1);
}
for (int i = 1; i <= n; ++i) b[i] = f[i] + g[i] - 1;
for (int i = 1; i <= n; ++i) a[i] = a[i - 1] + b[i];
memset(F, 0x3f, sizeof F);
for (int i = 1; i <= n; ++i) F[i][i] = 0, m[i][i] = i;
for (int t = 2; t <= n; ++t) {
for (int i = 1, j = t; j <= n; ++j, ++i) {
for (int k = m[i][j - 1]; k <= m[i + 1][j]; ++k) {
if (F[i][k] + F[k + 1][j] + a[j] - a[i - 1] < F[i][j]) {
F[i][j] = F[i][k] + F[k + 1][j] + a[j] - a[i - 1];
m[i][j] = k;
}
}
}
}
cout << "Case " << zeq << ": " << F[1][n] << '\n';
}
return 0;
}
/*
f[i][j] = min(f[k][j - 1] + W(k + 1, i));
*/