P4170

[CQOI2007]涂色

题目描述

假设你有一条长度为 \(5\) 的木板,初始时没有涂过任何颜色。你希望把它的 \(5\) 个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为 \(5\) 的字符串表示这个目标:\(\texttt{RGBGR}\)

每次你可以把一段连续的木板涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木板涂成 \(\texttt{RRRRR}\),第二次涂成 \(\texttt{RGGGR}\),第三次涂成 \(\texttt{RGBGR}\),达到目标。

用尽量少的涂色次数达到目标。

输入格式

输入仅一行,包含一个长度为 \(n\) 的字符串,即涂色目标。字符串中的每个字符都是一个大写字母,不同的字母代表不同颜色,相同的字母代表相同颜色。

输出格式

仅一行,包含一个数,即最少的涂色次数。

样例 #1

样例输入 #1

AAAAA

样例输出 #1

1

样例 #2

样例输入 #2

RGBGR

样例输出 #2

3

提示

\(40\%\) 的数据满足 \(1\le n\le 10\)

\(100\%\) 的数据满足 \(1\le n\le 50\)

其实我觉得挺难的
开始完全想复杂了
s[l]==s[r]时转移应该是f[l][r]=min(f[l+1][r],f[l][r-1])
s[l]!=s[r]时转移考虑分断点k f[l][r]=min(f[l][k]+f[k+1][r])
还是用记忆化写 方便边界处理
点击查看代码
#include<bits/stdc++.h>
using namespace std;
string s;
int n,f[155][155];
int dp(int l,int r)
{
	if(f[l][r])return f[l][r];
	if(l==r)return f[l][r]=1;
	if(s[l]==s[r])return f[l][r]=min(dp(l,r-1),dp(l+1,r));
	int res=INT_MAX;
	for(int k=l;k<r;k++)
		res=min(res,dp(l,k)+dp(k+1,r));
	return f[l][r]=res;
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>s;
	n=s.length();
	s=" "+s;
	cout<<dp(1,n)<<"\n";
	return 0;
}
posted @ 2023-01-17 22:15  PKU_IMCOMING  阅读(16)  评论(0)    收藏  举报