
题目大意
给定一个长为 (n) 的字符串表示染色目标,每次只能把连续的一段染成同一颜色,求最少染色次数。
(1 leqslant n leqslant 50)
题目链接
BZOJ 1260
题解
区间 DP。
记 (f[i, ; j]) 表示区间 ([i, ; j]) 的答案,转移为: [
f[i, ; j] =
begin{cases}
begin{align}
min(f[i + 1, ; j], ; f[i, ; j - 1], ; f[i + 1,; j - 1] + 1) &quad s[i] = s[j] \
min(f[i, ; k] + f[k + 1, ; j]) &quad s[i] neq s[j]
end{align}
end{cases}
] 其中 (s) 为目标,答案为 (f[1, ; n])。
被数据范围吓到了。。。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
#include <climits> #include <cstring> #include <algorithm> const int MAXN = 55; int f[MAXN][MAXN]; char s[MAXN]; void (int n) { for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) f[i][j] = i == j ? 1 : INT_MAX; for (int l = 1; l < n; l++) for (int i = 1; i <= n - l; i++) { int j = i + l; if (s[i] == s[j]) { if (l == 1) f[i][j] = 1; else f[i][j] = std::min(std::min(f[i + 1][j], f[i][j - 1]), f[i + 1][j - 1] + 1); } else for (int k = i; k < j; k++) f[i][j] = std::min(f[i][j], f[i][k] + f[k + 1][j]); } } int main() { scanf("%s", s + 1); int n = strlen(s + 1); dp(n); printf("%dn", f[1][n]); return 0; }
|
近期评论