C++ 多状态dp

目录

按摩师

打家劫舍

打家劫舍2

删除并获得点数

粉刷房子


按摩师

面试题 17.16. 按摩师

最大值问题

f : 预约此次的最长时间    g :不预约此次的最长时间

出现的错误:return max(f[n - 1]), g[n - 1]);  

注意:①题目没给nums的范围,if(n == 0) return 0;没有判0,就会报错

 ②奇怪的是不是在执行的时候报错,而是在运行样例的时候报这个错误

参考代码

class Solution {
public:
    int massage(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n), g(n);
        if(n == 0) return 0;
        f[0] = nums[0];
        for(int i = 1; i < n; i++)
        {
            f[i] = g[i - 1] + nums[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[n - 1], g[n - 1]);
        //return max(f[n - 1]), g[n - 1]);
    }
};

打家劫舍

198. 打家劫舍

参考代码

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n), g(n);
        f[0] = nums[0];
        for(int i = 1; i < n; i++)
        {
            f[i] = g[i - 1] + nums[i];
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[n - 1], g[n - 1]);
    }
};

打家劫舍2

213. 打家劫舍 II

最大值问题

f : 取当前位置的值,且是当前位置为结尾的最大值

g:不取当前位置的值,且是当前位置为结尾的最大值

注意点:①传到函数参数的问题,这里的有效区间是[left, right]

②按照nums[0] 去与不取划分,因为nums.size() >= 1,按照nums[2]划分这么写会出现下标越界

参考代码

class Solution {
public:
    int rob(vector<int>& nums) {
        return max(nums[0] + _rob(nums, 2, nums.size() - 2), _rob(nums, 1, nums.size() - 1));
    }
    int _rob(vector<int>& nums, int left, int right)
    {
        if(left > right) return 0;
        int n = nums.size();
        vector<int> f(n), g(n);
        // vector<int> f[n], g[n];
        f[left] = nums[left];
        for(int i = left + 1; i <= right; i++)
        {
            f[i] = g[i - 1] + nums[i];
            g[i] = max(g[i - 1], f[i - 1]);
        }
        return max(f[right], g[right]);
        // return max(f[i], g[i]);
    }
};

删除并获得点数

740. 删除并获得点数

注释掉的也对,没发现写成arr[i - 1],10000取不上,然后改成10002

参考代码1

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        // vector<int> f(10002), g(10002), arr(10002);
        // for(auto e : nums)
        //     arr[e] += e;

        // for(int i = 1; i <= 10001; i++)
        // {
        //     f[i] = g[i - 1] + arr[i - 1];
        //     g[i] = max(g[i - 1], f[i - 1]);
        // }
        // return max(f[10001], g[10001]);
        vector<int> f(10001), g(10001), arr(10001);
        for(auto e : nums)
            arr[e] += e;
        f[0] = arr[0];
        for(int i = 1; i < 10001; i++)
        {
            f[i] = g[i - 1] + arr[i];
            g[i] = max(g[i - 1], f[i - 1]);
        }
        return max(f[10000], g[10000]);
    }
};

注意:①这个地方是arr[i] , 不是nums[i]

☆☆②变量名和函数名一样

vs下可以看出,这里的max是一个变量不是函数 ,对于下面的报错的理解:这不是一个函数,不能有()

明显调用的表达式前的括号必须具有(指针)函数类型 

也不是不能改:

力扣下:报错也是很明显了    被调用的对象不是函数或者函数指针

参考代码2

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        int n = nums.size();
        int m = 0;
        for(auto e : nums)
            m = max(e, m);
        vector<int> f(m + 1), g(m + 1), arr(m + 1);
        for(auto e : nums)
            arr[e] += e;
        f[0] = arr[0];//可以不写,因为最小是1;
        for(int i = 1; i < m + 1; i++)
        {
            f[i] = g[i - 1] + arr[i];//
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(g[m], f[m]);
    }
};

粉刷房子

LCR 091. 粉刷房子

我写的都是没有扩容,一维dp初始化的并不多,且不用偏移量

错误 ①return min(red[n - 1], max(blue[n - 1], green[n - 1]));

参考代码

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        int n = costs.size();
        vector<int> red(n), blue(n), green(n);
        red[0] = costs[0][0];
        blue[0] = costs[0][1];
        green[0] = costs[0][2];
        for(int i = 1; i < n; i++)
        {
            red[i] = min(blue[i - 1], green[i - 1]) + costs[i][0];
            blue[i] = min(red[i - 1], green[i - 1]) + costs[i][1];
            green[i] = min(red[i - 1], blue[i - 1]) + costs[i][2];
        }
        return min(red[n - 1], min(blue[n - 1], green[n - 1]));
        // return min(red[n - 1], max(blue[n - 1], green[n - 1]));
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值