动态规划 DP (三)

4.分割DP

对于分割类型题,动态规划的状态转移方程通常并不依赖相邻的位置,而是依赖于满足分割
条件的位置。
1)
力扣icon-default.png?t=N5K3https://leetcode.cn/problems/perfect-squares/举个例子对于8来说,要计算 完全平方数的最少数量 ,需要依次遍历:8-1*1, 8-2*2这两个数的 完全平方数的最少数量 ,选择最少的那个,然后加一,就是8的 完全平方数的最少数量 。
所以转移方程是
dp[i] = 1 + min(dp[i-1*1], dp[i-2*2], dp[i-3*3], ......dp[i-j*j])  (i-j*j>=0)
class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0] = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j*j<=i;j++){
                dp[i] = min(dp[i], dp[i-j*j]+1);
            }
        }
        return dp[n];
    }
};

2)

力扣icon-default.png?t=N5K3https://leetcode.cn/problems/decode-ways/当前元素的解码方法,取决于当前元素和前一个元素

如果结合起来是一个11到26之间的数字 ,那说明当前元素有两种解码方法,一种是与前一个元素结合,一种是独立成为一个数字

如果结合起来是10,那说明当前元素只有一种解码方法,就是与前一个元素结合,因为0不能独立存在

如果结合起来是一个不在10到26之间的数字,那说明当前元素只有一种解码方法,就是独立成为一个数字

除此之外,再考虑一下不存在解码方法的情况就可以了。

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> dp(n+1,1);
        
        if((s[0]-'0')==0) return 0;
        if(n<2) return n;
        int pre = s[0]-'0';
        for(int i=2;i<=n;i++){
            int cur = s[i-1] - '0';
            if((pre==0||pre>2)&&cur==0){
                return 0;
            }
            if((pre==1)||(pre==2 && cur<7)){
                if(cur==0){
                    dp[i] = dp[i-2];
                }else{
                    dp[i] = dp[i-1] + dp[i-2];
                }
            }else{
                dp[i] = dp[i-1];
            }

            pre = cur;
        }
        return dp[n];

    }
};

3)

力扣icon-default.png?t=N5K3https://leetcode.cn/problems/word-break/

这道题比较清晰,每当子串与字典中的词相等时,当前的状态就会等于字符串中减掉字串的坐标的状态。这样两重遍历后,就可以得到结果。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        int n = s.size();
        vector<bool> dp(n+1, false);
        dp[0] = true;
        for(int i=1;i<=n;i++){
            for(string w:wordDict){
                int len = w.length();
                if(i>=len && s.substr(i-len, len)==w){
                    dp[i] = dp[i] || dp[i-len];
                }
            }
        }
        return dp[n];
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值