【动态规划算法练习】day4


一、213. 打家劫舍 II

1.题目简介

213. 打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
在这里插入图片描述
在这里插入图片描述

2.解题思路

在这里插入图片描述

3.代码

class Solution {
public:
    int func(vector<int>& nums, int start, int end)
    {
        vector<int> v(2, 0);
        vector<vector<int>> dp(nums.size(), v);
        dp[start][0] = 0;//不偷第一家
        dp[start][1] = nums[start];//偷第一家
        for(int i = start + 1;i < end; ++i)
        {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
            dp[i][1] = dp[i - 1][0] + nums[i];
        }
        return max(dp[end - 1][0], dp[end - 1][1]);
    }
    int rob(vector<int>& nums) {
        if(nums.size() == 1) return nums[0];
        //分两种情况:1.不考虑偷最后一间房,但是考虑偷前一间房;2.考虑偷最后一间房,但是不考虑偷前一间房(两间房都不考虑偷的情况,隐藏在这两种情况中)
        return max(func(nums, 0, nums.size() - 1), func(nums, 1, nums.size()));
    }
};

4.运行结果

在这里插入图片描述

二、740. 删除并获得点数

1.题目简介

740. 删除并获得点数

给你一个整数数组nums,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。
在这里插入图片描述

2.解题思路

在这里插入图片描述

3.代码

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        map<int, int> m;
        vector<int> v;
        for(auto& e : nums)
        {
            m[e]++;
        }
        for(auto& e : m)
        {
            v.push_back(e.first);
        }
        vector<int> vp(2, 0);
        vector<vector<int>> dp(v.size(), vp);
        //从0~i,不删除i点可以获得的最大点数;删除i点将获得的最大点数
        dp[0][0] = 0;//不删除该点可以获得的最大点数
        dp[0][1] = v[0] * m[v[0]];//删除该点将获得的最大点数
        for(int i = 1;i < v.size(); ++i)
        {
            if(v[i - 1] == v[i] - 1)
            {
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
                dp[i][1] = dp[i - 1][0] + v[i] * m[v[i]];
            }
            else//如果前一个值与当前值并不是相邻数,则删除当前数不会影响前一个数,因此要取删除或者不删除前一个值所能得到的较大点数
            {
                dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
                dp[i][1] = max(dp[i - 1][0], dp[i - 1][1]) + v[i] * m[v[i]];
            }
        }
        return max(dp[v.size() - 1][0], dp[v.size() - 1][1]);
    }
};

4.运行结果

在这里插入图片描述

三、剑指 Offer II 091. 粉刷房子

1.题目简介

剑指 Offer II 091. 粉刷房子
在这里插入图片描述

2.解题思路

在这里插入图片描述

3.代码

class Solution {
public:
    int minCost(vector<vector<int>>& costs) {
        vector<int> v(3, 0);
        vector<vector<int>> dp(costs.size(), v);
        dp[0][0] = costs[0][0];//刷红色的最小花费
        dp[0][1] = costs[0][1];//刷蓝色的最小花费
        dp[0][2] = costs[0][2];//刷绿色的最小花费
        for(int i = 1;i < costs.size(); ++i)
        {
            dp[i][0] = min(dp[i - 1][1] , dp[i - 1][2]) + costs[i][0];//刷红色的最小花费
            dp[i][1] = min(dp[i - 1][0] , dp[i - 1][2]) + costs[i][1];//刷蓝色的最小花费
            dp[i][2] = min(dp[i - 1][0] , dp[i - 1][1]) + costs[i][2];//刷绿色的最小花费 
        }
        return min(min(dp[costs.size() - 1][0], dp[costs.size() - 1][1]), dp[costs.size() - 1][2]);
    }
};

4.运行结果

在这里插入图片描述


总结

今天是算法练习的第4天。
宝剑锋从磨砺出,梅花香自苦寒来,继续加油!
如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codeJinger

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值