【洛谷】題解 P4170 【[CQOI2007]塗色】
阿新 • • 發佈:2019-01-06
f[i][j]表示從i到j染色最少需要多少次
如果a[i]==a[j],可以從f[i+1][j],f[i][j-1],f[i+1][j-1]+1三個狀態轉移。
否則對區間進行分裂,從小區間轉移。
程式碼:
// luogu-judger-enable-o2
//#define LOCAL
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <bits/stdc++.h>
#define INF 0x3f
#define ull unsigned long long
#define ll long long
#define FOR(a, b, n) for(int a = b; b >= n ? a >= n : a <= n; b >= n ? a-- : a++)
#define M(a, n) memset(a, n, sizeof(a));
#define S(n) scanf("%s", n)
#define P(n) printf("%d", n)
#define G(n) getline(cin, n)
#define PI acos(-1.0)
using namespace std;
const int NR = 60;
int f[NR][NR], n, a[NR];
char b[NR];
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while(ch <= '0' || ch > '9') {
if(ch == '-') {
w = -1;
ch = getchar();
}
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
int main() {
S(b + 1);
int n = strlen(b + 1);
int j, l;
FOR(i, 1, n)
a[i] = b[i] - 'A' + 1;
M(f, 0x3f);
FOR(i, 1, n)
f[i][i] = 1;
FOR(l, 2, n) {
for(int i = 1; i + l - 1 <= n; i++) {
j = i + l - 1;
if(a[i] == a[j]) {
f[i][j] = min(f[i + 1][j], f[i][j - 1]);
f[i][j] = min(f[i][j], f[i + 1][j - 1] + 1);
}
else {
FOR(k, i, j - 1) {
f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
}
}
}
}
P(f[1][n]);
}