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;
}
posted @ 2020-06-14 22:12  pyyyyyy  阅读(151)  评论(0编辑  收藏  举报