[CQOI2007]涂色

原题链接

题解

\(f[i][j]\) 表示对 \(i\)\(j\) 的字串染色最少多少次,设字符串为 \(c\),有 \(3\) 种情况:

  1. \(i=j\) 时,也就是只有一个字符,染色一次就可以了。转移方程为 \(f[i][i]=1(1 \le i \le n)\)

  2. \(i\not=j\)\(c[i]=c[j]\) 时,有 \(2\) 种染色方法:\(i+1,j\)\(i,j-1\)。对于第一种方法,我们在染第一次色时把 \(i\)\(j\) 的所有点都染成 \(j\) 的颜色,然后就可以满足 \(c[i]=c[j]\),其余的点再使用其他染料覆盖即可。同理,对于第二种情况,一样的。最后取最小值,所以转移方程就是:\(f[i][j]=min(f[i+1][j],f[i][j-1])\)

  3. \(i\not=j\)\(c[i]\not=c[j]\) 时,则枚举一个断点 \(k\),两边的和就是答案。转移方程:

\[f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])(i \le k < j) \]

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=60;
char c[N];
int f[N][N];
int main()
{
	scanf("%s",c+1);
	int n=strlen(c+1);
	memset(f,63,sizeof f);
	for(int i=1;i<=n;i++)
		f[i][i]=1;
	for(int len=2;len<=n;len++)
	for(int i=1;i<=n-len+1;i++)
	{
		int j=i+len-1;
		if(c[i]==c[j])
		{
			f[i][j]=min(f[i+1][j],f[i][j-1]);
			continue;
		}
		for(int k=i;k<j;k++)
			f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
	}
	cout<<f[1][n];
	return 0;
}
posted @ 2022-07-06 11:29  Epoch_L  阅读(61)  评论(0)    收藏  举报