(M)Dynamic Programming:2 Keys Keyboard

来源:互联网 发布:电脑怎么检查网络 编辑:程序博客网 时间:2024/05/22 06:19

这个题也是用的递归,回溯,不知道怎么用动态规划。类似的题用回溯的其实很多,就是这种给两种操作,求达到要求的时候操作次数最少能有几次。这道题就是,如果当前复制的东西加上当前字符串的个数到了n,就返回,如果不到n,就考虑两种情况,要么把现在所有的字符都复制再粘贴,要么还是粘贴上次复制的个数。这里我加了一个处理,如果当前复制的东西加上去之后超过了n,那么返回一个很大的数,因为不满足条件。

class Solution {public:    int minSteps(int n) {        if(n == 1)            return 0;        return minSteps(n, 1, 1, 1);    }    int minSteps(int n, int al_times, int pastenum, int nownum)    {        int x = nownum + pastenum;        if(x > n)            return INT_MAX;        if(x == n)        {            return al_times +1;        }        else        {            return min(minSteps(n, al_times + 2, x, x),minSteps(n, al_times+1, pastenum, x));        }    }};
但是这道题也有动态规划的解法,建立一个数组dp,dp[i]存放n为i的情况下的最少次数,如果n=6,遍历n=1~5的情况,发现3能整除6,那么dp[3]+6/3次能得到6,2也能被6整除,那么dp[2]+6/2次也能得到6,遍历找到最小的就可以了。
class Solution {public:    int minSteps(int n) {        int *dp = new int[n+1];        for (int i = 2; i <= n; i++) {            dp[i] = i;            for (int j = i-1; j > 1; j--) {                if (i % j == 0) {                    dp[i] = min(dp[i], dp[j] + (i/j));                }                            }        }        return dp[n];    }};