P4170 [CQOI2007]涂色
题意
给定一个长为\(n\)的序列,每次可以把一段涂成某种颜色,后涂的会覆盖先涂的,问最少涂几次能得到目标状态
\(n\le50\)
思路
设\(f[i][j]\)表示\(i\)到\(j\)最少的涂色数量
分情况讨论
\(i=j\)时,显然有\(f[i][j]=1\)
$ i\neq j$时
-
如果\(a[i] = a[j]\),就继承一下上一次涂的色,\(f[i][j]=\min(f[i+1][j],f[i][j-1])\)
-
如果\(a[i]\neq a[j]\),就把颜色看成两段,枚举分割点\(k\),\(f[i][j]=\min(f[i][k]+f[k+1][j])\)
\(code\)
/*
@ author:pyyyyyy/guhl37
-----思路------
-----debug-------
*/
#include<bits/stdc++.h>
using namespace std;
const int N=2020;
int f[N][N];
char s[N];
int main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%s",s+1);
int len=strlen(s+1);
memset(f,0x3f3f3f,sizeof(f));
for(int i=1; i<=len; ++i) f[i][i]=1;
for(int k=2; k<=len; ++k) {
for(int i=1; i<=len-k+1; ++i) {
int j=i+k-1;
if(s[i]==s[j]) f[i][j]=min(f[i+1][j],f[i][j-1]);
else if(s[i]!=s[j])
for(int l=i; l<=j-1; ++l) f[i][j]=min(f[i][l]+f[l+1][j],f[i][j]);
}
}
cout<<f[1][len];
return 0;
}
$$Life \quad is \quad fantastic!$$