664. Strange Printer

题目:
There is a strange printer with the following two specialrequirements:
The printer can only print a sequence of the same character each time.
At each turn, the printer can print new characters starting from and ending at any places, and will cover the original existing characters.
Given a stringconsists of lower English letters only, your job is to count the minimum numberof turns the printer needed in order to print it.
Example 1:
Input: “aaabbb”
Output: 2
Explanation: Print “aaa” first and then print”bbb”.
Example 2:
Input: “aba”
Output: 2
Explanation: Print “aaa” first and then print”b” from the second place of the string, which will cover theexisting character ‘a’.
Hint: Length of the given string will not exceed 100.
解题思路:
1)对长度为Len的字符串,可以将其分解为两部分单独打印,安装切分点的不同,共有Len-1种组合,所有组合中最小的打印次数即为该字符串的最少打印次数。对字符串的第i+1个字符到j+1个字符组成的子串,用p(i,j)表示其最少打印次数,则本题的解为p(0,Len-1),且有递推表达式
这里写图片描述
递推表达式第二项表示如果切分成的两个子串最后一个字符相同,则可以少打印一次,因为在打印第一个子串最后一个字符的时候可以同时将第二个子串全部打印,从而减少一次打印。
C++实现的递归算法:

int strangePrinter(string s) {
         intlen = s.length();
         if(len <= 1) return len;
         returnhelpPrint(s, 0, len);//表示字符串结束位置的下一个位置
}

int helpPrint(string s, int start, int end){
         intlen = end-start;
         if(len <= 1) return len;
         intnum = len;
         for(int i = start; i < end-1; i++){
                 inttem = helpPrint(s, start, i+1) + helpPrint(s, i + 1, end);
                 if(s[i] == s[end-1]) tem-=1;
                 num= num < tem ? num : tem;
         }
         returnnum;
}

2)递归程序,提交OJ,超时,嗝屁!
由于具有最优子结构的特点,显然可以用动态规划求解的,麻烦的捋清楚填表顺序。对字符串S的第i+1个字符到第j+1个字符组成的子串,还是P(i,j)用表示其最少打印次数。以长度为4的字符串,演示填表顺序
这里写图片描述
根据上述递推关系,由于下标i<=j,矩阵P(Len-1,Len-1)为三角形,填表方向是沿对角线元素依次向右上角填充。
C++的动态规划算法实现:

int strangePrinter(string s) {
         intlen = s.length();
         if(len <= 1) return len;
         intdp[100][100];
         for(int i = 0; i < len; i++){
                 for(int j = i; j < len; j++){
                          dp[i][j]= j - i + 1;
                 }
         }
         for(int i = 1; i < len; i++){//间隔遍历
                 for(int j = 0; j+i < len; j++){//层数遍历
                          for(int k = j; k < j+i; k++){
                                   auto tem = dp[j][k] + dp[k + 1][j + i];
                                   if(s[k] == s[j + i]) tem--;
                                   dp[j][j+ i] = min(dp[j][j + i], tem);
                          }
                 }
         }
         returndp[0][ len - 1];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值