【bzoj1260】[CQOI2007]涂色paint
题意:就是说一开始一个序列是空的,然后每次可以将连续的一段染成同一颜色,问多少次才能到目标状态。
一开始想的是二分,然后题解DP。。。
f[i][j]表示区间[i,j]需要染色多少次
首先初始状态是f[i][i]=1和f[i][i+1]=str[i]==str[i+1]
然后从短区间地推到长区间
对于f[i][j],若str[i]==str[j],则有f[i][j]=min{f[i+1][j],f[i][j-1],f[i+1][j-1]+1},否则f[i][j]=min{f[i][k]+f[k+1][j]∣i≤k<j}
复杂度:O(n^3)
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 60 int len; int f[N][N]; char str[N]; int main() { scanf("%s",str+1); len=strlen(str+1); memset(f,127/3,sizeof(f)); for (int i=1;i<=len;i++) f[i][i]=1; for (int l=1;l<=len;l++) for (int i=1;i<=len-l;i++) { int j=i+l; if (str[i]==str[j]) if (l==1) f[i][j]=1; else { 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);删了这句更快,0ms。。 } else for (int k=i;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); } printf("%d\n",f[1][len]); return 0; }