【LCP19】【DP】每日一题day29

32 篇文章 0 订阅
14 篇文章 0 订阅

天哪!LeetCode的每日一题终于不是树啦!前几天觉得题目类型有些重复,都是一看就会写的_(:з」∠)_ 开始了动态规划!字符串!!正是我薄弱的地方,希望接下来一个月都是这些能让我好好学习学习

这道题一眼就能看出来是我不会的dp。因为[红,黄,红]每一块的长度不固定,真的不知道该怎么设定它的状态,如何状态转移也毫无头绪,好像当前叶子和它的前一片叶子关系不大。

我们试着按照动态规划的思路来分析一下:

一、找子问题
子问题必定是和叶子的颜色有关的。对于每一片叶子,有三种状态:在左边的红色区域、在中间的黄色区域、在右边的红色区域。还需要记录它的位置,我们选定从左往右推,所以子问题就是从第0片叶子到第i片叶子,第i片叶子处于某一状态时的最小操作数。

这道题由于它是一个全局的红黄红,所以一开始很难想到怎么分割成子问题。这里“子问题”的含义和递归、贪心非常不同,不是把问题分割成几块、每一块去寻找最优解、或是形式相同规模变小,而是你思考问题的时候,是怎样一步步得到最后结果的,是一个思考步骤上的“子”关系。

二、确定状态
由上述分析,设f[i][j]表示从第0片叶子到第i片叶子,第i片叶子为状态j时所需的最小操作数(j = 0,1,2)。

三、边界状态
考虑最先开始下手的第0片叶子,如果是红色,就不需要操作,f[0][0] = 0, 如果是黄色,f[0][0] = 1;
它不可能是状态1、2,由于这道题是取最小值,我们就把不可能的状态设为一个很大的数。这里要注意,我一开始用的是INT_MAX,但是它再+1就溢出了,因为leaves不超过50片,所以我直接INT_MAX / 2, 用INT_MAX的时候一定要小心。
再看第1片叶子,它不可能是状态2,也设为INT_MAX / 2。

四、状态转移
这个很简单就不用写了嘛

class Solution {
public:
    int minimumOperations(string leaves) {
        int size = leaves.length();
        int f[size][3];
        memset(f, 0, sizeof(f));
        if (leaves[0] == 'y')
        {
            f[0][0] = 1;
        }
        f[0][1] = f[0][2] = f[1][2] = INT_MAX / 2;
        for (int i = 1; i < size - 1; i++)
        {
            if (leaves[i] == 'y')
            {
                f[i][0] = f[i - 1][0] + 1;
                f[i][1] = min(f[i - 1][0], f[i - 1][1]);
                f[i][2] = min(f[i - 1][1], f[i - 1][2]) + 1;
            }
            else
            {
                f[i][0] = f[i - 1][0];
                f[i][1] = min(f[i - 1][0], f[i - 1][1]) + 1;
                f[i][2] = min(f[i - 1][1], f[i - 1][2]);
            }
        }
        if (leaves[size - 1] == 'y')
        {
            f[size - 1][2] = min(f[size - 2][1], f[size - 2][2]) + 1;
        }
        else f[size - 1][2] = min(f[size - 2][1], f[size - 2][2]);
        f[size - 1][0] = f[size - 1][1] = INT_MAX / 2;
        
        return f[size - 1][2];
    }
};

我才知道for循环里面定义的变量只能在for循环里面用_(:з」∠)_

And这道题是昨天中秋和国庆双节时候的题,看官方题解的评论要笑死了哈哈哈哈哈哈哈
十月这么快就到了,感觉会是能学很多知识的一个月呢。现在觉得听着喜欢的音乐学习真是太舒服了,已经变成我最喜欢做的事情了(*^▽^*)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值