664. Strange Printer

来源:互联网 发布:华美淘宝客优惠券采集 编辑:程序博客网 时间:2024/06/11 12:29

题目:
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];}
原创粉丝点击