664. 奇怪的打印机
思路:
为什么动规有些规律就是发现不了呢,叹气。
一开始想的方向就错了,想的是用出现次数最多的先打满,然后再用次数第二多的覆盖,在第三的覆盖,但发现如果字母出现的位置不连续就很难做,需要存储一个字母出现的所谓位置,这样就很难实现了。
然后看了题解,发现还是找规律。
首先我们可以发现 ,aba,aba打的次数最少为2次,ab打印次数为2。bbab,打印次数为2次,bba打印次数为两次。我们可以推测如果s[i]=s[j]我们能得到一个结论,就是从s[i]打印到s[j]的打印次数等于s[i]打印到s[j-1]的次数。
如果s[i]!=s[j],我们可以想象再[i,j]这个区间里,一定会有最少的打印次数从i打到j,所以我们遍历[i,j]的所有情况找到最小的即可。例如,abab,有多少种情况?a,bab(1+2次);ab,ab(2+2);aba,b(2+1),所以最小的可能是3次。
根据上面两种情况我们就可以写出程序了。
代码
class Solution {
public:
int strangePrinter(string s) {
int n = s.length();
vector<vector<int> >dp(n,vector<int>(n,INT_MAX));
for(int i=n-1;i>=0;--i){
dp[i][i]=1; //[i,i]区间只有一种打印方式,就是他本身
for(int j=i+1;j<n;++j){
if(s[i]==s[j]){ //i位置元素等于j位置元素
dp[i][j] = dp[i][j-1];
}
else{
for(int k=i;k<j;++k){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); //从[i,j]区间找出打印次数最少的情况
}
}
}
}
return dp[0][n-1];
}
};