动态规划dp_4

news2025/2/21 7:07:07

一.背包

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

二.题

1.

思路:dp五部曲,思路在注释


/*
dp[i]表示:到达第 i 个台阶有dp[i]种方法
状态转移方程:dp[i] = dp[i-1] + dp [i-2] + dp[i-3] +  .... + dp[i-m]; 
既有:dp[i] +=dp[i-j];
初始化:从1到m都初始化为1
遍历方向,从下往上遍历
*/

#include <iostream>
#include <vector>

using namespace std;

int main(){
    int n,m;
    cin>>n>>m;
    
    vector<int>dp(n+1);
    for(int i = 1; i <= m; i++)dp[i] = 1;
    
    for(int i = 2; i <= n; i++){
        for(int j = 1;j <= m && j < i; j++){
            dp[i] += dp[i-j];
        }
    }
    cout<<dp[n];
    return 0;
}

 2.

思路:dp五部曲,思路在注释

/*
dp[i]:表示当钱为 i 时,最小的组成方式为dp[i]
状态转移方程:遍历钱有dp[i] = min(dp[i],dp[i-j]+1)
初始化:dp[0] = 1;
遍历顺序:先背包,后钱
*/

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int>dp(amount+1,INT_MAX);
        dp[0] = 0;

        for(int i = 1; i <= amount; i++){
            for(int j = coins.size()-1; j>=0; j--){
                int coin = coins[j];
                if(i>=coin&&dp[i-coin]!=INT_MAX)
                    dp[i] = min(dp[i],dp[i-coin]+1);
            }
        }
        if(dp[amount]==INT_MAX)return -1;
        else return dp[amount];
    }
};

3. 

思路:五部曲,注释

/*
dp[i]:当数为 i 时,完全平方数之和最小数量为dp[i]
状态转移方程:dp[i] = min(dp[i],dp[i-j*j]+1)
初始化:dp[0] = 0;
遍历顺序:都行
*/

class Solution {
public:
    int numSquares(int n) {

        vector<int>dp(n+1,INT_MAX);
        dp[0] = 0;

        for(int i = 1; i <= n;i++){
            for(int j = 1; j * j<= i; j++){
                dp[i] = min(dp[i],dp[i - j * j]+1);
            }
        }
        return dp[n];

    }
};

 4.这个题得收藏

 

思路: 

  1. 确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

  1. 确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

  1. dp数组如何初始化

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

那么dp[0]有没有意义呢?

dp[0]表示如果字符串为空的话,说明出现在字典里。

但题目中说了“给定一个非空字符串 s” 所以测试数据中不会出现i为0的情况,那么dp[0]初始为true完全就是为了推导公式。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

  1. 确定遍历顺序

题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品


class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        vector<bool> dp(s.size() + 1, false);
        dp[0] = true;
        for (int i = 1; i <= s.size(); i++) {   // 遍历背包
            for (int j = 0; j < i; j++) {       // 遍历物品
                string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
                if (wordSet.find(word) != wordSet.end() && dp[j]) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

5.多重背包

思路:01背包的变种题型,只需要多加一层for循坏来控制住次数即可

#include <iostream>
#include <vector>
using namespace std;

int C,N;

int main(){
    cin>>C>>N;
    vector<int>dp(C+1,0);// dp数组
    
    vector<int>weight(N+1);
    vector<int>value(N+1);
    vector<int>nums(N+1);
    
    for(int i = 1;i <= N;i++) cin>>weight[i];
    for(int i = 1;i <= N;i++) cin>>value[i];
    for(int i = 1;i <= N;i++) cin>>nums[i];
    
    for(int i = 0; i <= N; i++){  // 物品
        for(int j = C; j >= weight[i]; j--){  //背包
            
            for(int k = 1; k <= nums[i] && (j - k * weight[i])>=0; k++){
                dp[j] = max(dp[j],dp[j - k * weight[i]] + k * value[i]);
            }
            
        }
    }
    cout<<dp[C];
    return 0;
}

6.

思路:dp五部曲,思路在注释

/*
dp[i]:数组的含义为从 1 到 i 家 可偷取的最大金额为 dp[i]
状态转移方程:对于 i 号房子时 有 偷与不偷 俩个状态
偷 i 时 有 dp[i-2] + val[i]
不偷 i 时 有 dp[i-1]
既有 dp[i] = max(dp[i-1],dp[i-2]+val[i]);
初始化:对于 1 和 2房间来说,1是必偷的房间,而对于 2考虑max(val[1],val[2])
遍历顺序:从前往后
*/
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==1)return nums[0];
        else if(nums.size()==2)return max(nums[0],nums[1]);
        vector<int>dp(nums.size());
         
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);

        for(int i = 2;i < nums.size(); i++){
            dp[i] = max(dp[i-1],dp[i-2]+nums[i]);
        }
        return dp[nums.size()-1];
    }
};

 7.

思路:dp五部曲,思路在注释

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 1) return nums[0]; 
        if (nums.size() == 2) return max(nums[0], nums[1]); 


        vector<int> dp1(nums.size());
        dp1[0] = nums[0];
        dp1[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size() - 1; i++) {
            dp1[i] = max(dp1[i - 1], dp1[i - 2] + nums[i]);
        }


        vector<int> dp2(nums.size());
        dp2[0] = 0;
        dp2[1] = nums[1];
        for (int i = 2; i < nums.size(); i++) {
            dp2[i] = max(dp2[i - 1], dp2[i - 2] + nums[i]);
        }

        return max(dp1[nums.size() - 2], dp2[nums.size() - 1]);
    }
};

 8.

思路:注释

class Solution {
public:
    int rob(TreeNode* root) {
        vector<int> result = robTree(root);
        return max(result[0], result[1]);
    }
    // 长度为2的数组,0:不偷,1:偷
    vector<int> robTree(TreeNode* cur) {
        if (cur == NULL) return vector<int>{0, 0};
        vector<int> left = robTree(cur->left);
        vector<int> right = robTree(cur->right);
        // 偷cur,那么就不能偷左右节点。
        int val1 = cur->val + left[0] + right[0];
        // 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况
        int val2 = max(left[0], left[1]) + max(right[0], right[1]);
        return {val2, val1};
    }
};

9.

思路:贪心和动态规划

贪心

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int cost = INT_MAX, profit = 0;
        for (int price : prices) {
            cost = min(cost, price);
            profit = max(profit, price - cost);
        }
        return profit;
    }
};

 dp

/*
买入的价格是随着遍历更新最小值的
dp则是买入后更新的获利最大值

dp[i] : 表示当第 i 天卖出的最大值
状态转移方程:dp[i] = max(dp[i-1],prices[i] - min_in)
初始化:dp[0] = 0;
遍历顺序:前到后

*/

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (n == 0) return 0;

        int minprice = prices[0];
        vector<int> dp (prices.size(), 0);

        for (int i = 1; i < prices.size(); i++){
            minprice = min(minprice, prices[i]);
            dp[i] = max(dp[i - 1], prices[i] - minprice);
        }
        return dp[n - 1];
    }
};

10.

思路:五部曲,思路在注释

/*
dp含义
dp[i][0]: 表示为从第 1 天到 i 天持有股票时利润最大值为dp[i][0]
dp[i][1]: 表示为从第 1 天到 i 天不持有股票利润最大值为dp[i][1]
状态转移方程:
dp[i][0] = max(dp[i - 1][0],dp[i - 1][1] + prices[i]); // 手不持股票
dp[i][1] = max(dp[i - 1][1],dp[i - 1][0] - prices[i]); // 手持股票
初始化:
dp[0][0] = 0
dp[0][1] = -prices[0];
遍历顺序:
关系由递推得到,所以从头到尾
*/
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(),vector<int>(2));
        dp[0][0] = 0;dp[0][1] = -prices[0];

        for(int i = 1;i < prices.size(); i++){
            dp[i][0] = max(dp[i-1][0],dp[i-1][1]+prices[i]);
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }
        return dp[prices.size()-1][0];
    }
};

 11.算法竞赛进阶指南

思路:诶呦,我的妈呀 ,这是什么题?

找规律,先看小的n = 1,n = 2,n = 3的情况,然后调用递归函数

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
char mp[730][730];
void f(int n, int x, int y) {
	if (n == 1)mp[x][y] = 'X';
	else {
		int m = pow(3, n - 2);
		f(n - 1, x, y);
		f(n - 1, x + 2 * m, y);
		f(n - 1, x, y + 2 * m);
		f(n - 1, x + m, y + m);
		f(n - 1, x + 2 * m, y + 2 * m);
	}
}
int main() {
	int n;
	while (1) {
		cin >> n;
		if (n == -1) return 0;
		int c = pow(3, n - 1);
		memset(mp, ' ', sizeof(mp));
		f(n, 0, 0);
		for (int i = 0; i < c; i++) {
			for (int j = 0; j < c; j++) cout << mp[i][j];
			cout << endl;
		}
		cout << '-' << endl;
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

对贵司需求的PLC触摸的远程调试的解决方案

远程监控技术解决方案 一、需求痛点分析 全球设备运维响应滞后&#xff08;平均故障处理周期>72小时&#xff09;客户定制化需求频繁&#xff08;每月PLC程序修改需求超50次&#xff09;人力成本高企&#xff08;单次跨国差旅成本约$5000&#xff09;多品牌PLC兼容需求&am…

Python用PyMC3马尔可夫链蒙特卡罗MCMC对疾病症状数据贝叶斯推断

全文链接&#xff1a;https://tecdat.cn/?p39937 本文聚焦于马尔可夫链蒙特卡罗&#xff08;MCMC&#xff09;方法在贝叶斯推断中的Python实现。通过介绍MCMC的基础原理、在贝叶斯推断中的应用步骤&#xff0c;展示了其在解决复杂分布采样问题上的强大能力。同时&#xff0c;借…

网络工程师 (39)常见广域网技术

一、HDLC 前言 HDLC&#xff08;High-level Data Link Control&#xff0c;高级数据链路控制&#xff09;是一种面向比特的链路层协议。 &#xff08;一&#xff09;定义与历史背景 HDLC是由国际电信联盟&#xff08;ITU&#xff09;标准化的&#xff0c;它基于IBM公司早期的同…

每日Attention学习23——KAN-Block

模块出处 [SPL 25] [link] [code] KAN See In the Dark 模块名称 Kolmogorov-Arnold Network Block (KAN-Block) 模块作用 用于vision的KAN结构 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional as F import mathclass Swish(nn.Module)…

基于Python的Optimal Interpolation (OI) 方法实现

前言 Optimal Interpolation (OI) 方法概述与实现 Optimal Interpolation (OI) 是一种广泛应用于气象学、海洋学等领域的空间数据插值方法。该方法通过结合观测数据与模型预测数据&#xff0c;最小化误差方差&#xff0c;从而实现对空间数据的最优插值。以下是OI方法的一般步骤…

学习数据结构(10)栈和队列下+二叉树(堆)上

1.关于栈和队列的算法题 &#xff08;1&#xff09;用队列实现栈 解法一&#xff1a;&#xff08;参考代码&#xff09; 题目要求实现六个函数&#xff0c;分别是栈初始化&#xff0c;入栈&#xff0c;移除并返回栈顶元素&#xff0c;返回栈顶元素&#xff0c;判空&#xff0…

.NET版Word处理控件Aspose.Words教程:使用 C# 删除 Word 中的空白页

Word 文档中的空白页会使其看起来不专业并扰乱流程。用户会遇到需要删除 Word 中的空白页的情况&#xff0c;但手动删除它们需要时间和精力。在这篇博文中&#xff0c;我们将探讨如何使用 C# 删除 Word 中的空白页。 本文涵盖以下主题&#xff1a; C# 库用于删除 Word 中的空…

《代码随想录》刷题笔记——回溯篇【java实现】

文章目录 组合组合总和 III电话号码的字母组合组合总和组合总和II思路代码实现 分割回文串※思路字符串分割回文串判断效率优化※ 复原 IP 地址优化版本 子集子集 II使用usedArr辅助去重不使用usedArr辅助去重 递增子序列※全排列全排列 II重新安排行程题意代码 N 皇后解数独直…

【JavaEE进阶】验证码案例

目 &#x1f332;实现说明 &#x1f384;Hutool介绍 &#x1f333;准备工作 &#x1f334;约定前后端交互接口 &#x1f6a9;接口定义 &#x1f6a9;实现服务器后端代码 &#x1f6a9;前端代码 &#x1f6a9;整体测试 &#x1f332;实现说明 随着安全性的要求越来越⾼…

Qt Creator 5.0.2 (Community)用久了突然变得很卡

目录 1.现象 2.解决方案 1.现象 很久没有用Qt Creator开发项目了&#xff0c;刚刚结束的项目又是用VS2019开发的&#xff1b;这两天刚好有时间去学习一下Qt&#xff0c;刚好要用Qt Creator&#xff0c;结果一打开就没反应&#xff0c;主界面显示出来要好几分钟&#xff0c;最…

阅读论文笔记《Efficient Estimation of Word Representations in Vector Space》

这篇文章写于2013年&#xff0c;对理解 word2vec 的发展历程挺有帮助。 本文仅适用于 Word2Vect 的复盘 引言 这篇论文致力于探索从海量数据中学习高质量单词向量的技术。当时已发现词向量能保留语义特征&#xff0c;例如 “国王 - 男人 女人≈女王”。论文打算借助该特性&am…

初学PADS使用技巧笔记(也许会继续更新)

操作意图&#xff1a;网上找某个芯片封装又不想自己画&#xff0c;再加上没经验&#xff0c;怎么办&#xff1f; 就以AC-DC芯片PN8036为例&#xff0c;打开嘉立创的的DFM&#xff0c;打开立创商城&#xff0c;输入PN8036&#xff0c;点击数据手册&#xff0c;然后点击直接打开…

从无序到有序:上北智信通过深度数据分析改善会议室资源配置

当前企业普遍面临会议室资源管理难题&#xff0c;预约机制不完善和临时会议多导致资源调度不合理&#xff0c;既有空置又有过度拥挤现象。 针对上述问题&#xff0c;上北智信采用了专业数据分析手段&#xff0c;巧妙融合楼层平面图、环形图、折线图和柱形图等多种可视化工具&a…

CAS单点登录(第7版)4.管理

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 管理 概述 Admin Console & 仪表板 CAS 提供了许多可用于管理 CAS 服务器部署的工具和控制板。此类选项通常不是互斥的&#xff0c;旨在协同工作并呈现 CAS 配置和构建的各个方面&am…

Baklib一站式云平台:全场景赋能企业知识资产激活

内容概要 在数字化浪潮推动下&#xff0c;企业知识资产的高效管理与价值释放成为核心议题。Baklib作为一站式云平台&#xff0c;以全场景赋能为核心定位&#xff0c;通过构建知识中台架构&#xff0c;为企业提供从资源整合到应用落地的闭环解决方案。该平台不仅支持文本、图像…

登录弹窗效果

1&#xff0c;要求 点击登录按钮&#xff0c;弹出登录窗口 提示1&#xff1a;登录窗口 display:none 隐藏状态&#xff1b; 提示2&#xff1a;登录按钮点击后&#xff0c;触发事件&#xff0c;修改 display:block 显示状态 提示3&#xff1a;登录窗口中点击关闭按钮&#xff0…

小小小病毒(3)(~_~|)

一分耕耘一分收获 声明&#xff1a; 仅供损害电脑&#xff0c;不得用于非法。损坏电脑&#xff0c;作者一律不负责。此作为作者原创&#xff0c;转载请经过同意。 欢迎来到小小小病毒&#xff08;3&#xff09; 感谢大家的支持 还是那句话&#xff1a;上代码&#xff01; …

【Java 面试 八股文】Spring Cloud 篇

Spring Cloud 篇 1. Spring Cloud 5大组件有哪些&#xff1f;2. 服务注册和发现是什么意思&#xff1f;Spring Cloud 如何实现服务注册发现&#xff1f;3. 我看你之前也用过nacos&#xff0c;你能说下nacos与eureka的区别&#xff1f;4. 你们项目负载均衡如何实现的&#xff1f…

Esxi8.0设置nvidia显卡直通安装最新驱动

ESXI8.0设置显卡直通 在某些情况下&#xff0c;我们需要多次切换操作系统&#xff0c;以测试软件是否适用于特定系统和环境&#xff0c;减少多次重装系统的麻烦 ESXI8.0安装包 通过网盘分享的文件&#xff1a;ESXi-8.0U2-22380479-USB-NVME-集成网卡镜像.iso 链接: https://…

LabVIEW袜品压力测试系统

开发了一种基于LabVIEW开发的袜品压力测试系统。该系统利用LabVIEW并结合灵敏的传感器和高精度的处理模块&#xff0c;实现了对袜品压力的精确测量和分析。系统不同于传统的服装压力测试方法&#xff0c;为研究和评价袜子的舒适性提供了新的测试手段。 ​ 项目背景 该系统的…