题目链接:力扣
题意:
有台奇怪的打印机有以下两个特殊要求:
打印机每次只能打印由 同一个字符 组成的序列。
每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。
给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。
方法: 动态规划,dp[i][j]表示i到j最少的打印次数,i从后往前枚举,j从前往后枚举,每一次判断一下第i个字符和第j个字符是否相同,如果相同dp[i][j]就等于dp[i][j-1],如果不同,我们就把i,j这一段划分为两段i,k和k+1,j,dp[i][j]就是通过枚举i到j之间的每一个k,找到两段相加的最小打印次数,dp[i][j]取其值,这样子最后只需要返回dp[0][size-1]
class Solution {
public:
int strangePrinter(string s) {
int size = s.size();//统计字符串长度
vector<vector<int>> dp(size,vector<int>(size,1));//动态规划向量,dp[i][j]表示从第i个字符到第j个字符要打印的最少次数
for(int i=size-2;i>=0;i--)//枚举起始位置
{
for(int j=i+1;j<size;j++)//枚举结束位置
{
if(s[i]==s[j])//最后一个字符和第一个字符一样,那就只需要打一次
dp[i][j] = dp[i][j-1];//考虑i到j-1的最少需要打印的次数
else//最后一个字符和第一个字符不一样的话
{
int minn = INT_MAX;//初始化最小的打印次数
for(int k=i;k<j;k++)//将区间划分为两段,考虑两段各自的最少打印次数,然后和并起来
{
minn = min(minn,dp[i][k]+dp[k+1][j]);//获取最小的方案数
}
dp[i][j] = minn;//更新对应的dp值
}
}
}
return dp[0][size-1];//返回从0到size-1的最少打印次数
}
};