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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号