您现在的位置是:首页 > 编程 > 

【动态规划】陶然无喜亦无忧,人生且自由

2025-07-28 21:36:52
【动态规划】陶然无喜亦无忧,人生且自由 1. 师题目链接: 面试题 17.16. 师题目内容: 一个有名的师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替师到最优的预约集合(总预约时间最长),返回总的分钟数。注意:本题相对原题稍作改动示例 1:输入: [1,2,,1] 输出: 4 解释

【动态规划】陶然无喜亦无忧,人生且自由

1. 师

题目链接: 面试题 17.16. 师

题目内容:

一个有名的师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替师到最优的预约集合(总预约时间最长),返回总的分钟数。

注意:本题相对原题稍作改动

示例 1:

输入: [1,2,,1] 输出: 4 解释: 选择 1 号预约和 号预约,总时长 = 1 + = 4。 示例 2:

输入: [2,7,9,,1] 输出: 12 解释: 选择 1 号预约、 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。 示例 :

输入: [2,1,4,5,,1,1,] 输出: 12 解释: 选择 1 号预约、 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + + = 12。

第一 步骤分析

1. 状态表示 dp[i]表示选择到 i 位置时得最长预约时间. 选择到 i 位置时, 可由 i 位置是否选择分两种情况: f[i] 表示选择到 i 位置时 nums[i] 必选的最长时间. g[i] 表示选择到 i 位置时 nums[i] 不选的最长时间.

2. 状态转移方程

f[i]递推公式分析图

先分析关于f[i]的递推公式, 如上图, nums[i] 必选意味着nums[i-1]必定不选. 从起始点到[i-1]且nums[i-1]不选, 不就是g[i-1]吗? 所以f[i] = g[i-1] + nums[i];

g[i]递推公式分析图

再求g[i] 的递推公式 如上图, nums[i]不选, nums[i-1] 可选可不选. nums[i-1] 选择时, g[i] = f[i-1] nums[i-1] 不选时, g[i] = g[i-1] 又因为是求最大值,所以g[i] = (f[i-1],g[i-1]);

. 初始化 f[0] = nums[0]

4. 填表顺序 从左往右填表

5. 返回值 返回(f[n-1],g[n-1]);

第二 代码实现

代码语言:javascript代码运行次数:0运行复制
class Solution {
    public int massage(int[] nums) {
        //1. 创建dp表
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];
        //2. 初始化
        if(nums.length == 0) return 0;
        f[0] = nums[0];
        //. 填表
        for(int i = 1;i < n;++i) {
            f[i] = g[i-1] + nums[i];
            g[i] = (f[i-1],g[i-1]);
        }
        return (f[n-1],g[n-1]);
    }
}
2. 打家劫舍

题目链接: 21. 打家劫舍 II

题目内容:

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

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

示例 1:

输入:nums = [2,,2] 输出: 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 号房屋(金额 = 2), 因为他们是相邻的。 示例 2:

输入:nums = [1,2,,1] 输出:4 解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 号房屋(金额 = )。 偷窃到的最高金额 = 1 + = 4 。 示例 :

输入:nums = [1,2,] 输出:

提示:

1 <= nums.length <= 100 0 <= nums[i] <= 1000

第一 整体分析

由题意知, 偷了第一个位置就不能偷最后一个位置, 第一个位置的情况会影响动态规划的五个步骤, 于是需要分两种情况去讨论, 两种基本的步骤与上道题一致, 初始化和填表会有不同.

第二 动态规划

1. 状态表示 dp[i]表示偷到 i 位置的最高金额. 根据 i 位置的 偷 与 不偷 分两种状态: f[i] 表示 到 i 位置 nums[i]也偷的最高金额 g[i] 表示 到 i 位置 nums[i] 不偷的最高金额

2. 状态转移方程 跟上道题一样的分析思路,不多说明,直接给出结果: f[i] = g[i] + nums[i]; g[i] = (f[i-1],g[i-1]);

. 初始化 f[0] = nums[0]

4. 填表顺序 从左到右同时填表

5. 返回值 返回(x,y)

第三 代码实现

代码语言:javascript代码运行次数:0运行复制
class Solution {
    public int rob(int[] nums) {
        //1.创建dp表
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];
        int[] f1 = new int[n];
        int[] g1 = new int[n];
        //2.初始化
        if(n == 1) return nums[0];
        //第一个位置偷的初始化
        f[0] = nums[0];
        g[1] = nums[0];
        //第一个位置不偷的初始化
        f1[1] = nums[1];
        //.填表
        for(int i = 2;i < n-1;++i) {
            f[i] = g[i-1] + nums[i];
            g[i] = (f[i-1],g[i-1]);
        }
        int x = (f[n-2],g[n-2]);
        
        for(int i = 2;i < n;++i) {
            f1[i] = g1[i-1] + nums[i];
            g1[i] = (f1[i-1],g1[i-1]);
        }
        int y = (f1[n-1],g1[n-1]);
        return (x,y);
    }
}
. 删除并获得点数

题目链接: 740. 删除并获得点数

题目内容:

给你一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入:nums = [,4,2] 输出:6 解释: 删除 4 获得 4 个点数,因此 也被删除。 之后,删除 2 获得 2 个点数。总共获得 6 个点数。 示例 2:

输入:nums = [2,2,,,,4] 输出:9 解释: 删除 获得 个点数,接着要删除两个 2 和 4 。 之后,再次删除 获得 个点数,再次删除 获得 个点数。 总共获得 9 个点数。

提示:

1 <= nums.length <= 2 * 104 1 <= nums[i] <= 104

第一 预处理

直接上动态规划会发现选择完nums[i], 很难处理nums[i-1]和nums[i+1].所以先预处理nums数组. 创建一个arr数组, arr[i] 是 nums[i] 中 i 元素的总和, 比如arr[2] = 2+2 = 4 这样一来, 只要选了arr[i], 相邻位置就不能选了. 这其实就跟第一题"师"一样了.

第二 动态规划

1. 状态表示 dp[i] 表示选到 i 位置时的最大点数, 又根据arr[i] 是否选择分为两种情况: f[i] 表示到达 i 位置arr[i] 要选的最大点数 g[i] 表示到达 i 位置arr[i] 不选的最大点数

2. 状态转移方程 分析过程与第一题一样,便直接给出结果 f[i] = g[i-1] + arr[i]; g[i] = (g[i-1],f[i-1]);

. 初始化 f[0] = arr[0]; g[0] = 0;

4. 填表顺序 从左往右同时填

5. 返回值 返回(f[n-1],g[n-1]);

第三 代码实现

代码语言:javascript代码运行次数:0运行复制
class Solution {
    public int deleteAndEarn(int[] nums) {
        //预处理
        int n = 10001;
        int[] arr = new int[n];
        for(int x : nums) arr[x] += x;
        //创建dp表

        int[] f = new int[n];
        int[] g = new int[n];
        //初始化
        f[0] = arr[0];
        //填表
        for(int i = 1;i < n;++i) {
            f[i] = g[i-1] + arr[i];
            g[i] = (g[i-1],f[i-1]);
        }
        return (f[n-1],g[n-1]);
    }
}
4. 粉刷房子

题目链接: LCR 091. 粉刷房子

题目内容:

假如有一排房子,共 n 个,每个房子可以被粉刷成红、蓝或者绿这三种颜中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜不能相同。

当然,因为市场上不同颜油漆的价格不同,所以房子粉刷成不同颜的花费成本也是不同的。每个房子粉刷成不同颜的花费是以一个 n x 的正整数矩阵 costs 来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成红的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿的花费,以此类推。

请计算出粉刷完所有房子最少的花费成本。

示例 1:

输入: costs = [[17,2,17],[16,16,5],[14,,19]] 输出: 10 解释: 将 0 号房子粉刷成蓝,1 号房子粉刷成绿,2 号房子粉刷成蓝。 最少花费: 2 + 5 + = 10。 示例 2:

输入: costs = [[7,6,2]] 输出: 2

提示:

costs.length == n costs[i].length == 1 <= n <= 100 1 <= costs[i][j] <= 20

第一 步骤分析

1. 状态表示 dp[i] 表示到达 i 位置粉刷完所有房子的最小花费. 根据 i 位置粉刷的颜可以继续细分: dp[i][0] 表示到达 i 位置, i 粉刷红的最小花费 dp[i][1] 表示到达 i 位置, i 粉刷蓝的最小花费 dp[i][2] 表示到达 i 位置, i 粉刷绿的最小花费

2. 状态转移方程 先分析dp[i][0], 当i-1位置是蓝时, dp[i][0] = dp[i-1][1] + costs[i][0]; 当i-1位置是红时, dp[i][0] = dp[i-1][2] + costs[i][0]; 又因为要求最小花费, 所以: dp[i][0] = (dp[i-1][1],dp[i-1][2]) + costs[i][0]; 同理dp[i][1] = (dp[i-1][0],dp[i-1][2]) + costs[i][1]; dp[i][2] = (dp[i-1][0],dp[i-1][0]) + costs[i][2];

. 初始化 ①: 不创建虚拟节点, 就直接dp[0][0] = costs[0][0]; dp[0][1] = costs[0][1]; dp[0][2] = costs[0][2]; ②: 创建虚拟节点需要处理两个细节 第一 dp表与原数组之间的下标对应关系是: dp[i][0] -> costs[i-1][0]

第二 虚拟节点的初始化, 为了保证填表的正确, 比如填写dp[i][0]表, 为了保证dp[1][0] 必须为 costs[0][0], 看递推公式dp[i][0],所以dp[0][1] = 0,dp[0][2] = 0; 同理 dp[0][0] = 0

4. 填表顺序 从左往右填写三个表.

5. 返回值 有虚拟节点时, (dp[n][0],(dp[n][1],dp[n][2])); 无虚拟节点时, 把 n 改成 n-1即可.

第二 代码实现

代码语言:javascript代码运行次数:0运行复制
class Solution {
    public int minCost(int[][] costs) {
        // //创建dp表(不带虚拟节点)
        // int n = costs.length;
        // int[][] dp = new int[n][];
        // //初始化dp表
        // //dp[0][0],dp[0][1],dp[0][2]默认值即可
        // dp[0][0] = costs[0][0];dp[0][1] = costs[0][1];dp[0][2] = costs[0][2];
        // //填表
        // for(int i = 1;i < n;++i) {
        //     dp[i][0] = (dp[i-1][1],dp[i-1][2]) + costs[i][0];//注意原数组与dp表下标映射关系.
        //     dp[i][1] = (dp[i-1][0],dp[i-1][2]) + costs[i][1];
        //     dp[i][2] = (dp[i-1][0],dp[i-1][1]) + costs[i][2];
        // }
        // return (dp[n-1][0],(dp[n-1][1],dp[n-1][2]));

        //创建dp表(带虚拟节点)
        int n = costs.length;
        int[][] dp = new int[n+1][];
        //初始化dp表
        //dp[0][0],dp[0][1],dp[0][2]默认值即可
        
        //填表
        for(int i = 1;i <= n;++i) {
            dp[i][0] = (dp[i-1][1],dp[i-1][2]) + costs[i-1][0];//注意原数组与dp表下标映射关系.
            dp[i][1] = (dp[i-1][0],dp[i-1][2]) + costs[i-1][1];
            dp[i][2] = (dp[i-1][0],dp[i-1][1]) + costs[i-1][2];
        }
        return (dp[n][0],(dp[n][1],dp[n][2]));

    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-12-24,如有侵权请联系 cloudcommunity@tencent 删除dpint动态规划模型数组

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1220557.html

相关标签:无
上传时间: 2025-07-25 14:58:58
留言与评论(共有 20 条评论)
本站网友 五角场巴黎春天
2分钟前 发表
每间房内都藏有一定的现金
本站网友 产业研究报告
25分钟前 发表
5
本站网友 牧歌ktv
7分钟前 发表
i 粉刷红的最小花费 dp[i][1] 表示到达 i 位置
本站网友 大城市铁岭
2分钟前 发表
请计算出粉刷完所有房子最少的花费成本
本站网友 成都限购升级
6分钟前 发表
看递推公式dp[i][0]
本站网友 肠胃不适
9分钟前 发表
删除 2 获得 2 个点数
本站网友 半断食疗法
9分钟前 发表
示例 2:输入: [2
本站网友 担保公司是做什么的
5分钟前 发表
很难处理nums[i-1]和nums[i+1].所以先预处理nums数组. 创建一个arr数组
本站网友 华工主页
13分钟前 发表
蓝或者绿这三种颜中的一种
本站网友 早产儿的护理
3分钟前 发表
分享自作者个人站点/博客
本站网友 我看吧
0秒前 发表
f[i] = g[i] + nums[i]; g[i] = (f[i-1]
本站网友 大猪蹄子
30分钟前 发表
nums[i]不选
本站网友 徐州租房信息
23分钟前 发表
nums[i]不选
本站网友 股市二八现象
9分钟前 发表
当然
本站网友 催奶的方法
15分钟前 发表
2提示
本站网友 东部华侨城官网
28分钟前 发表
g[n-1]); 第二 代码实现 代码语言:javascript代码运行次数:0运行复制class Solution { public int massage(int[] nums) { //1. 创建dp表 int n = nums.length; int[] f = new int[n]; int[] g = new int[n]; //2. 初始化 if(nums.length == 0) return 0; f[0] = nums[0]; //. 填表 for(int i = 1;i < n;++i) { f[i] = g[i-1] + nums[i]; g[i] = (f[i-1]
本站网友 周其林
23分钟前 发表
1] 输出: 12 解释: 选择 1 号预约
本站网友 相亲网站
10分钟前 发表
蓝或者绿这三种颜中的一种
本站网友 叫板的意思
11分钟前 发表
1