理解题目

首先,我们需要清楚地理解题目要求。我们有一个长度为的木版,初始时没有任何颜色。我们的目标是通过最少的涂色次数,将木版涂成给定的目标颜色序列。每次涂色可以选择任意一段连续的区间,并将该区间内的所有部分涂成同一种颜色。后续的涂色会覆盖之前的颜色。

解题思路

这个问题类似于“区间动态规划”(Interval DP)的问题。我们需要找到一个状态表示和状态转移方程,以计算出最少需要多少次涂色才能达到目标。

状态定义

定义 为将区间 涂成目标颜色所需的最少涂色次数。

状态转移

考虑如何从更小的区间转移到更大的区间:

基本情况:当时,即区间长度为1,只需要涂色一次,因此

区间分割:对于区间,我们可以考虑以下两种情况:

情况1:如果 ,那么可以在涂 的时候顺便涂另一个。因此,可以从 或 dp[i+1][j] 转移而来。

例如,RGBGR 中 ,可以在涂时先涂 ,然后处理中间部分。

情况2:如果,那么我们需要将区间分成两部分,分别涂色。即对于所有

初始化

所有长度为的区间

最终代码

#include <bits/stdc++.h>
#define ll long long 
#define endl "\n"
using namespace std;
const int N=50+5;
string s;
int sop;
int dp[N][N];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin>>s;
	sop=s.size();
	for(int i=0;i<sop;i++){
		dp[i][i]=1;
	}
	for(int len=2;len<=sop;len++){
		for(int l=0;l+len-1<sop;l++){
			int r=l+len-1;
			if(s[l]==s[r]){
				dp[l][r]=dp[l+1][r];
			}else{
				dp[l][r]=INT_MAX;
				for(int k=l;k<r;k++){
					dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
				}
			}
		}
	}
	cout<<dp[0][sop-1];
	return 0;
}