[CQOI2007]涂色

题目

潮考我的题,之后我就给秒了

显然这个数据范围很是区间\(dp\),我们设\(dp[i][j]\)表示把区间\([i,j]\)染成目标颜色的最小花费

首先初始化显然\(dp[i][i]=1\)

区间\(dp\)的常规套路显然,枚举断点\(i\leq k<j\)\(dp[i][j]=min(dp[i][k]+dp[k+1][j])\)

观察这个题的一个性质,如果\(S[i]=S[j]\),那么那么\(dp[i][j]\)这个状态可以直接继承\(dp[i+1][j]\)\(dp[i][j-1]\),我们可以视为出示涂的时候直接把\([i,j]\)这段都涂了,这样涂这个新格子的花费就算在最开始的初始化里了

代码

#include<cstdio>
#include<cstring>
#define re register
#define min(a,b) ((a)<(b)?(a):(b))
int n,dp[55][55];
char S[55];
int main() {
	scanf("%s",S+1);n=strlen(S+1);
	memset(dp,20,sizeof(dp));
	for(re int i=1;i<=n;i++) dp[i][i]=1;
	for(re int p=2;p<=n;p++) 
		for(re int i=1;i+p-1<=n;i++) {
			re int j=i+p-1;
			if(S[i]==S[j]) {
				dp[i][j]=min(dp[i+1][j],dp[i][j]);
				dp[i][j]=min(dp[i][j-1],dp[i][j]);
			}
			for(re int k=i;k<j;k++) 
				dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]);
		}
	printf("%d\n",dp[1][n]);
	return 0;
}
posted @ 2019-05-30 20:47  asuldb  阅读(266)  评论(0编辑  收藏  举报