【动态规划专栏】专题三:简单多状态dp--------2.打家劫舍II

简介: 【动态规划专栏】专题三:简单多状态dp--------2.打家劫舍II


题目来源

本题来源为:

Leetcode213. 打家劫舍 II

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

题目解析

这道题是在打家劫舍I的基础上加上了首尾相连的不能盗窃。

算法原理

在写状态表示之前,先预处理一下:

分两种情况,在1位置时选不选择盗窃;

要是选择在0位置不盗窃:

就转化成了在1~n-1区间内进行一次打家劫舍I问题。

要是选择在0位置盗窃:

就转化成了在2~n-2区间内进行一次打家劫舍I问题。

因此就将环形问题就转化成了线性问题:

在第一个位置分成两种情况:偷还是不偷。

接下来就是分析打家劫舍I问题了

1.状态表示

经验+题目要求

对于本题而言就是:

f[i]表示:选择到i位置时,偷nums[i],此时的最大金额
g[i]表示:选择到i位置时,不偷nums[i],此时的最大金额

2.状态转移方程

根据状态表示,分两种情况:

因此状态方程为:

f[i]=g[i-1]+nums[i];
g[i]=max(f[i-1],g[i-1]);
max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1))

3.初始化

只有0位置会发生越界,初始化一下0位置即可

4.填表顺序

从左往右,两个表同时填

5.返回值

返回:

代码实现

动态规划的代码基本就是固定的四步:

1.创建dp表
2.初始化
3.填表
4.返回值

本题完整代码实现:

class Solution 
{
public:
    int rob(vector<int>& nums) 
    {
        int n=nums.size();
        return max(nums[0]+rob1(nums,2,n-2),rob1(nums,1,n-1));
    }
    int rob1(vector<int>& nums,int left,int right)
    {
        if(left>right)
        return 0;
        //创建dp表
        int n=nums.size();
        vector<int> f(n);
        vector<int> g(n);
        //初始化
        f[left]=nums[left];
        //填表
        for(int i=left+1;i<=right;i++)
        {
            f[i]=g[i-1]+nums[i];
            g[i]=max(f[i-1],g[i-1]);
        }
        //返回值
        return max(f[right],g[right]);
    }
};

打家劫舍I的完整代码如下:

class Solution 
{
public:
    int rob(vector<int>& nums) 
    {
        //创建dp表
        int n=nums.size();
        vector<int> f(n);
        vector<int> 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]);
    }
};
相关文章
|
11月前
|
设计模式 Java
「全网最细 + 实战源码案例」设计模式——生成器模式
生成器模式(Builder Pattern)是一种创建型设计模式,用于分步骤构建复杂对象。它允许用户通过控制对象构造的过程,定制对象的组成部分,而无需直接实例化细节。该模式特别适合构建具有多种配置的复杂对象。其结构包括抽象建造者、具体建造者、指挥者和产品角色。适用于需要创建复杂对象且对象由多个部分组成、构造过程需对外隐藏或分离表示与构造的场景。优点在于更好的控制、代码复用和解耦性;缺点是增加复杂性和不适合简单对象。实现时需定义建造者接口、具体建造者类、指挥者类及产品类。链式调用是常见应用方式之一。
171 12
|
网络协议 物联网 开发者
详细介绍 MQTT 的工作原理,包括 MQTT 协议的特点、核心概念以及消息传递的流程
详细介绍 MQTT 的工作原理,包括 MQTT 协议的特点、核心概念以及消息传递的流程
7616 1
|
Linux Docker 容器
docker启动完美容器的过程
本文详细介绍了使用Docker创建和管理容器的过程,包括拉取镜像、搜索镜像、创建容器、启动、停止、删除容器,以及查看容器日志和进程信息的常用命令。
601 2
|
SQL 关系型数据库 MySQL
必知的 MySQL 索引失效场景【包括实践验证】,别再踩坑了!(上)
必知的 MySQL 索引失效场景【包括实践验证】,别再踩坑了!
1640 2
|
文字识别 API 开发工具
印刷文字识别使用问题之如何进行批量识别
印刷文字识别产品,通常称为OCR(Optical Character Recognition)技术,是一种将图像中的印刷或手写文字转换为机器编码文本的过程。这项技术广泛应用于多个行业和场景中,显著提升文档处理、信息提取和数据录入的效率。以下是印刷文字识别产品的一些典型使用合集。
|
存储 大数据 数据处理
探索现代数据中心的冷却技术
【5月更文挑战第25天】 在信息技术迅猛发展的今天,数据中心作为其核心基础设施之一,承载了巨大的数据处理需求。随着服务器密度的增加和计算能力的提升,数据中心的能耗问题尤其是冷却系统的能效问题日益凸显。本文将深入探讨现代数据中心所采用的高效冷却技术,包括液冷解决方案、热管技术和环境自适应控制等,旨在为数据中心的绿色节能提供参考和启示。
|
数据格式 索引
🍉一文辨析Number()函数、parseInt()函数与parseFloat()函数
🍉一文辨析Number()函数、parseInt()函数与parseFloat()函数
746 2
|
Python
Python-Merge多个Scanpy-Adata对象和细胞降采样实现
本分简单分享在Python中操着合并Adata对象,和细胞降采样的实现方法
1244 0
|
机器学习/深度学习 编解码 固态存储
【机器视觉】Python+OpenCV+MediaPipe实时人流检测
MediaPipe 人脸检测是一种超快的人脸检测解决方案,带有 6 个地标和多人脸支持。它基于 BlazeFace,这是一种轻量级且性能良好的人脸检测器,专为移动 GPU 推理量身定制。检测器的超实时性能使其能够应用于任何需要准确的面部感兴趣区域作为其他任务特定模型输入的实时取景器体验。
1096 0
【机器视觉】Python+OpenCV+MediaPipe实时人流检测
优质!从Sql到Nosql,redis+mysql从架构到优化全覆盖
Redis是一个远程内存数据库,它不仅性能强劲,而且还具有复制特性以及为解决问题而生的独一无二的数据模型。Redis 提供了5种不同类型的数据结构,各式各样的问题都可以很自然地映射到这些数据结构上:Redis的数据结构致力于帮助用户解决问题,而不会像其他数据库那样,要求用户扭曲问题来适应数据库。除此之外,通过复制、持久化( persistence )和客户端分片( client side sharding )等特性,用户可以很方便地将Redis扩展成一个能够包含数百GB数据、每秒处理上百万次请求的系统。