代码随想录训练营30-动态规划3

一、0/1背包问题

参考博客,主要注意以下几个方面:

1 背包问题要素: 背包容积、物品价值、物品体积

2 dp含义,dp[j]表示为j体积下,最大的物品价值。

3 遍历顺序,如果是二维写法,可以不关心顺序,但是如果是一维写法,需要关心遍历顺序

4 初始化值,需要根据dp定义含义做初始化定义。

二、416 分割等和子集

主要是怎么思考,去和01背包问题联系起来:

首先,dp[j]代表什么?容量为j的背包,所背的物品价值最大可以为dp[j]。dp[j]表示背包总容量(所能装的总重量)是j,放进物品后背包的最大重量为dp[j]。换句话说,在此题目中,背包容积和价值都是num[x]。所以状态公式为:

dp[j] = max(dp[j] , dp[j - nums[i]] + nums[i])

考虑初始化情况,当dp[0]应该为0,总容量为0,能背的最大的重量也为0 

遍历顺序应该先遍历物品 再遍历体积。

//sum
#define MAX(a, b) (((a) > (b)) ? (a) : (b))

int getSum(int* nums, int numsSize)
{
   int sum = 0;
   for(int i = 0; i < numsSize; i++)
   {
      sum += nums[i]; 
   }
   return sum;
}

bool canPartition(int* nums, int numsSize) {
    int sum = 0;
    sum = getSum(nums, numsSize);
    if(sum % 2)
    {
        return false;
    }

    //初始化dp
    int target = sum/2;
    int* dp = (int*)calloc((target + 1), sizeof(int));
    
    for(int i = 0 ; i < numsSize; i++)
    {
        for(int j = target; j >= nums[i]; j--)
        {
            dp[j] = MAX(dp[j], dp[j - nums[i]] + nums[i]);
        }
    }

    return dp[target] == target;

}

另外,二维数组的写法如下:

//sum
#define MAX(a, b) (((a) > (b)) ? (a) : (b))

int getSum(int* nums, int numsSize)
{
   int sum = 0;
   for(int i = 0; i < numsSize; i++)
   {
      sum += nums[i]; 
   }
   return sum;
}

bool canPartition(int* nums, int numsSize) {
    int sum = 0;
    sum = getSum(nums, numsSize);
    if(sum % 2)
    {
        return false;
    }

    //初始化dp
    int target = sum/2;
    int** dp = (int**)malloc(sizeof(int*) * (numsSize+1));
    for(int i = 0; i <= numsSize; i++)
    {
        dp[i] = (int*)calloc(target + 1, sizeof(int));
    }

    for(int j = nums[0]; j <= target; ++j) {
        dp[0][j] = nums[0];
    }
    for(int i = 1; i < numsSize; i++)
    {
        for(int j = 1; j <= target; j++)
        {
            //状态转移公式
            // 若当前背包重量j小于nums[i],则其值等于只考虑0到i-1物品时的值
            if(j < nums[i])
                dp[i][j] = dp[i - 1][j];
            // 否则,背包重量等于在背包中放入num[i]/不放入nums[i]的较大值
            else
                dp[i][j] = MAX(dp[i - 1][j], dp[i - 1][j  - nums[i]] + nums[i]);
        }
    }

    if(target == dp[numsSize - 1][target])
    {
        return true;
    }

    return false;
}

三、1049 最后一块石头重量II

 一开始阅读题目,根本联系不到01背包,但是仔细分析,题目可以转化为求2堆相近的石头,这样大堆减小堆石头,得到的值应该就是最小值。但是怎么求其中某一堆石头呢?

结合分割等和子集,找到一个target,利用01背包,就可以找到最大的dp,即找到最大的石头堆。怎么获取target,一个整体分成两部分,那么和对半分,就是需要石头堆的最大值。

int getSum(int* stones, int stonesSize)
{
    int sum  = 0;
    for(int i = 0; i < stonesSize; i++)
    { 
        sum += stones[i];
    }

    return sum;
}
#define MAX(a, b)  (a) > (b)? (a) : (b)
int lastStoneWeightII(int* stones, int stonesSize) {
    //把问题拆分成:划分成两块相近的石头堆,就可以使用0、1背包
    int dp[15001] = {0};//根据题目限制
    int max_stone = getSum(stones, stonesSize);
    int target = (getSum(stones, stonesSize))/2;
    //目标就是找到sum的一半下dp最大值。
    for(int i = 0; i < stonesSize; i++)
    {
        for(int j = target; j >= stones[i]; j--)
        {
            dp[j] = MAX(dp[j], dp[j - stones[i]] + stones[i]);
        }
    }

    return max_stone - dp[target] * 2;
}

四、494 目标和

题目主要点还是如何转化:本题要如何使表达式结果为target,既然为target,那么就一定有 left组合 - right组合 = target。left + right = sum,而sum是固定的。right = sum - left。

left - (sum - left) = target

推导出 left = (target + sum)/2 。

target是固定的,sum是固定的,left就可以求出来。

此时问题就是在集合nums中找出和为left的组合。

left可以理解为正数之和, right就是负数之和,因为题目描述 + -两个运算符,只可能这两个情况。

题目转化成01背包问题。

还需要注意点,就是前面的背包问题是求最大值。但是这里求的是多少种可能组合。所以dp含义是有区别的。

int findTargetSumWays(int* nums, int numsSize, int target) {
    //题目是说找多少种方案
    if(numsSize <= 0)
    {
        return 0;
    }
    int sum  = 0;
    for(int i = 0; i < numsSize; i++)
    {
        sum += nums[i];
    }
    if(abs(target) > sum)
    {
        return 0;
    }
    if((sum + target) % 2)
    {
        return 0;
    }
    //初始化dp
    int bagsize = (sum + target)/2;//正数
    int* dp = (int*)calloc(bagsize + 1, sizeof(int));
    dp[0] = 1;
    for(int i = 0; i < numsSize; i++)
    {
        for(int j = bagsize; j >= nums[i]; j--)
        {
            dp[j] += dp[j - nums[i]];
        }
    }
    
    return dp[bagsize];
}

五、474 一和零

这里关注点是0和1是两个维度(m 和 n相当于是一个背包,两个维度的背包)。dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。递推公式为:

dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

#define MAX(a, b)  (a) > (b)? (a) : (b)
int findMaxForm(char** strs, int strsSize, int m, int n) {
    int** dp = (int**)malloc(sizeof(int*) * (m + 1));
    for(int i = 0; i <= m; i++)
    {
        dp[i] = calloc(n + 1, sizeof(int));
    }
    //初始化成0

    for(int i = 0; i < strsSize; i++)
    {
       int zeroNum = 0;
       int oneNum = 0;

       for(int j = 0; j < strlen(strs[i]); j++)
       {
          if(strs[i][j] == '0')
          {
            zeroNum++;
          }
          else
          {
            oneNum++;
          }
       }
       
       for(int p = m; p >= zeroNum; p--)
       {
          for(int q = n; q >= oneNum; q--)
          {
            dp[p][q] = MAX(dp[p][q], dp[p - zeroNum][q - oneNum] + 1);
          }
       }
    }

    return dp[m][n];
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基础IO认识

回顾文件 我们之前认识文件只是在语言程度上理解&#xff0c;但是我们理解的不够彻底&#xff0c;要想真正理解文件要在os上理解。 简单代码认识 1 #include<stdio.h>2 int main(){3 FILE* fpfopen("log.txt","w");4 if(fpNULL){5 p…

浅析边缘计算技术

概念 边缘计算是一种分布式计算范式&#xff0c;它将计算任务和数据存储从中心化的云端推向网络的边缘&#xff0c;即设备或终端&#xff0c;以提高响应速度和降低网络带宽需求。在边缘计算中&#xff0c;数据在源头附近进行处理和分析&#xff0c;而不需要将所有数据传输到…

21世纪世界十大名人颜廷利:真正的幸福是快乐, 真正的理想是远航

真正的财富是分享, 真正的情感是珍藏; 真正的人生是奋斗, 真正的自由是飞翔; 真正的幸福是快乐, 真正的理想是远航… &#xff08;升命学说&#xff09; 21世纪东方哲学家思想家、科学家、当代中国教育界知名教授、专业周易起名改名字、易经姓名学专家、目前比较有影响力的人…

【C++第七课-string用法】

这里写自定义目录标题 string的初步介绍sring的构造函数string的构造函数-重点掌握无参的构造函数用常量字符串来初始化拷贝构造 string的构造函数-非重点掌握拷贝字符串str从pos位置开始的len个字符拷贝字符串s的前n个字符用n个c去初始化 string的赋值string的遍历和访问下标[…

docker如何生成springboot镜像

1、在springboot的jar包所在的目录下创建Dockerfile文件&#xff0c;此案例的目录为/usr/java Dockerfile的文件内容如下&#xff1a; FROM openjdk:8 LABEL author"zengyanhui" LABEL email"1181159889qq.com" WORKDIR /usr/java/springbootdemo COPY s…

TCP的特性(4)

TCP特性 拥塞控制(可靠性机制)延迟应答(效率机制)捎带应答(效率机制)面向字节流(粘包问题)TCP异常机制小结 拥塞控制(可靠性机制) 虽然TCP引入了滑动窗口,能够高效可靠的传输大量数据,但是在开始阶段就发送大量数据,可能引起一系列问题. TCP引入了慢启动机制,先发少量的数据,判…

PDF Shaper Ultimate 免安装中文破姐版 v14.1

软件介绍 PDF Shaper是一套完整的多功能PDF编辑工具&#xff0c;可实现最高的生产力和文档安全性。它允许你分割&#xff0c;合并&#xff0c;水印&#xff0c;署名&#xff0c;优化&#xff0c;转换&#xff0c;加密和解密您的PDF文件&#xff0c;也可插入和移动页&#xff0…

RabbitMQ知识点总结和复习

之前项目中用到RabbitMQ的场景主要是订单信息的传递&#xff0c;还有就是利用RabbitMQ的死信队列属性设置&#xff0c;实现延迟队列效果&#xff0c;实现超时支付取消功能&#xff0c;以及在两个不同项目中传递数据等场景。 最近几年的工作中都是一直用的RabbitMQ&#xff0c;…

【C++】深入剖析C++11 initializer_list 新的类功能 可变模板参数

目录 一、std::initializer_list 1、std::initializer_list是什么类型 2、std::initializer_list 的应用场景 ①给自定义容器赋值 ② 传递同类型的数据集合 二、新的类功能 1、默认成员函数 2、关键字default 3、关键字delete 三、可变参数模板 一、std::initialize…

关于Linux的“三十年河东,三十年河西”的思考

目录 一、何为“三十年河东&#xff0c;三十年河西”&#xff1f; 二、Linux系统的发展历程简介 三、Linux家族 四、Linux发展分支 五、关于对Linux发展的回顾 一、何为“三十年河东&#xff0c;三十年河西”&#xff1f; “三十年河东&#xff0c;三十年河西”原义是三十…

OpenWRT有线桥接部署教程

前言 之前咱们讲到OpenWRT部署WAN实现PPPoE拨号上网和自动获取IP模式上网的办法&#xff1a; OpenWRT设置PPPoE拨号教程 OpenWRT设置自动获取IP&#xff0c;作为二级路由器 这一次&#xff0c;咱们尝试用OpenWRT有线桥接上一级路由器的教程。 可能有小伙伴敏锐地发现了&am…

20232803 2023-2024-2 《网络攻防实践》实践八报告

目录 1. 实践内容2. 实践过程2.1 动手实践任务一2.2 动手实践任务二&#xff1a;分析Crackme程序2.2.1 crackme1.exe2.2.2 crackme2.exe 2.3 分析实践任务一2.4 分析实践任务二 3. 学习中遇到的问题及解决4. 学习感悟、思考等 1. 实践内容 动手实践任务一&#xff1a;对提供的r…

【Python编程实践1/3】模块

目录 目标 模块 import ​编辑 代码小结 题目 from...import 随机模块 代码小结 randint函数 骰子大战 choice函数 总结 目标 拧一颗螺丝&#xff0c;只会用到螺丝刀&#xff1b;但是修一台汽车&#xff0c;需要一整套汽修的工具。函数就像螺丝刀&#xff0c;可以帮…

Go实战训练之Web Server 与路由树

Server & 路由树 Server Web 核心 对于一个 Web 框架&#xff0c;至少要提供三个抽象&#xff1a; Server&#xff1a;代表服务器的抽象Context&#xff1a;表示上下文的抽象路由树 Server 从特性上来说&#xff0c;至少要提供三部分功能&#xff1a; 生命周期控制&…

FIFO Generate IP核使用——Native读写接口信号详解

Native FIFO接口信号是用于FIFO IP核与外部电路进行通信的信号。当FIFO支持独立的写和读时钟时&#xff0c;这些信号可以包括标准端口和可选端口。 1 当FIFO具有独立时钟时的接口信号 当FIFO具有独立的时钟时&#xff0c;其接口信号会相应地有所变化。特别是关于复位信号rst…

Hibernate入门学习

目录 1、ORM思想概述 2、自定义ORM框架 3、第一个Hibernate程序开发步骤&#xff08;重要&#xff09; 1&#xff09;下载完整包 2&#xff09;创建项目&#xff0c;导入所需jar包 3&#xff09;建立student表 4&#xff09;创建和student表对应的Student实体类 5&…

postman中百度preview无法加载的解决方案

问题 在使用postman关联时&#xff0c;百度接口与天气接口已使用glb_city关联&#xff0c;但在百度接口发送请求时&#xff0c;发现preview无法加载 解决方案 1、进入百度 百度全球领先的中文搜索引擎、致力于让网民更便捷地获取信息&#xff0c;找到所求。百度超过千亿的中…

基于Springboot的民航网上订票系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的民航网上订票系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

vue3 + ts 快速入门(全)

文章目录 学习链接1. Vue3简介1.1. 性能的提升1.2.源码的升级1.3. 拥抱TypeScript1.4. 新的特性 2. 创建Vue3工程2.1. 基于 vue-cli 创建2.2. 基于 vite 创建&#xff08;推荐&#xff09;vite介绍创建步骤项目结构安装插件项目结构总结 2.3. 一个简单的效果Person.vueApp.vue …

11个2024年热门的AI编码助手

大家好&#xff0c;人工智能&#xff08;AI&#xff09;领域的大型语言模型&#xff08;LLMs&#xff09;已经逐渐发展成熟&#xff0c;并且深入到了我们日常的工作当中。在众多AI应用中&#xff0c;编码助手尤为突出&#xff0c;是开发人员编写更高效、准确无误代码的必备辅助…
最新文章