1. 程式人生 > >【洛谷】題解 P4170 【[CQOI2007]塗色】

【洛谷】題解 P4170 【[CQOI2007]塗色】

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]); }