动态规划-背包问题总述

简介: DP,Dynamic Programming. 背包问题是这样一类问题——背包有重量限制,要往背包里放物品。每样物品都有自己的价值v与重量w。问怎样放使得背包里物品的总价值最大。 参考文档:大牛之作-《背包问题九讲》 - 01背包:每样东西只有一个,要么放,要么不放,所以得名01背包 - 完全背包:每样物品都没有个数限制 - 不完全背包:不同物品的个数不尽相同

DP,Dynamic Programming.
背包问题是这样一类问题——背包有重量限制,要往背包里放物品。每样物品都有自己的价值v与重量w。问怎样放使得背包里物品的总价值最大。
参考文档:大牛之作-《背包问题九讲》
- 01背包:每样东西只有一个,要么放,要么不放,所以得名01背包
- 完全背包:每样物品都没有个数限制
- 不完全背包:不同物品的个数不尽相同


1. 01背包

1.1 背包不要求装满

1.1.1状态转移方程

dp[i][j]表示以下两种约束下的最大价值:

  • 1.所装物品为前[0,i]种,不一定每种物品都要放进去;
  • 2.所放物品总重量<=j。
    那么状态转移方程

dp[i][j]={max(dp[i1][j],dp[i1][jw[i]]+v[i])dp[i1][j]j>=w[i]j<w[i]

通俗地讲就是:
dp[i][j]={max(,i)iii

1.1.2 状态初始化

dp[][]数组初始化为0.
当数组下标为负越界时也返回0.

1.2背包必须装满

1.2.1状态转移方程

同1.1.1.

1.2.2 状态初始化

dp[i][j]={0i=0j=0

1.2.3 状态初始化的比较

初始化的dp[][]数组,事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可以在什么也不装且价值为0的情况下“恰好装满”。其他容量的背包均没有合法的解,属于未定义的状态,应该被赋值为负无穷。

1.3 dp数组降维

时间与空间复杂度都为O(NW),其中空间复杂度可以优化。
可以将dp[][]降维为一位数组dp[]。此时我们期望第i次循环后dp[j]表示的就是二维时的dp[i][j]。
那么dp[j]=f(dp[j],dp[j-w[i]]),即dp[j]的值与dp[j]和dp[j-w[i]]有关
这要求每次主循环(i循环)中,我们要以for(int j=V;j>=0;j–){}这样的逆序来遍历。只有这样才能保证计算dp[j]时dp[j-w[i]]保存的是dp[i-1][j-w[i]]的值。反例见1.3.1.

1.3.1 关于j降序的反例

令背包总重W=2.
只有编号为0的一件物品,w[0]=1,v[0]=2。很显然,对于01背包,最大的价值V为2.
若j升序,主循环i取0时,先算dp[1]=2;再算dp[2]=max(dp[2],dp[2-w[0]]+v[0])=max(0,2+2)=4,显然不对。
降维的AC代码可参见:动态规划 HDOJ2602-Bone Collector-01背包

1.4 典型OJ题目

可参见动态规划 HDOJ2602-Bone Collector-01背包

2.不完全背包

3.完全背包

3.1状态转移方程

可以把完全背包转化为0-1背包求解。
第i件物品可以不装,可以装1件、2件、。。。、k件。根据这个思想得到状态转移方程:

dp[i][j]=max(dp[i1][j],dp[i1][jkw[i]]+kv[i])|j>=kw[i])(1)

很明显,i,j,k三层循环,在OJ中很容易超时。

3.2 合理的时间复杂度

需要减掉k这一层循环。
由于一件物品装过之后还可以再装,得到状态转移方程:

dp[i][j]=max(dp[i1][j],dp[i][jw[i]]+v[i])(2)

同样地,可以给dp[][]数组降维。此时j的遍历顺序为升序。
dp[j]=max(dp[j],dp[jw[i]]+v[i])(3)

3.3典型OJ题目

可参见:动态规划 HDOJ-1114 完全背包

目录
相关文章
|
4月前
|
算法
【动态规划专栏】背包问题:目标和
【动态规划专栏】背包问题:目标和
35 0
|
1月前
|
算法 Java 测试技术
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
这篇文章介绍了基于动态规划法的三种算法:解决背包问题的递归和自底向上实现、Warshall算法和Floyd算法,并提供了它们的伪代码、Java源代码实现以及时间效率分析。
算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法
|
3月前
|
算法 Java 决策智能
Java数据结构与算法:动态规划之背包问题
Java数据结构与算法:动态规划之背包问题
|
4月前
|
机器学习/深度学习 算法 机器人
【动态规划】【C++算法】741摘樱桃
【动态规划】【C++算法】741摘樱桃
BXA
|
算法 程序员 决策智能
动态规划详解背包问题及实践(附C++代码)
背包问题是一个经典的组合优化问题,它可以被抽象为一个把物品放入背包中的过程,以求最终背包中物品价值的最大化
BXA
566 0
|
算法 C语言
【软考总结】-<算法>动态规划法--0-1背包问题
在上篇博客中,我们讲了动态规划法在最长公共子序列问题中的应用,(详情请见博客《算法:动态规划法--最长公共子序列》)。这次学习了0-1背包问题,对动态规划法的思想理解了更深了一层,以下是我的简单理解,希望能为路过的读者带来帮助。
245 0
|
算法 调度
算法基础课第八章动态规划和贪心算法
算法基础课第八章动态规划和贪心算法
97 0
算法基础课第八章动态规划和贪心算法
|
算法
《趣学算法-动态规划-0-1背包问题》阅读笔记
《趣学算法-动态规划-0-1背包问题》阅读笔记
127 0
《趣学算法-动态规划-0-1背包问题》阅读笔记
代码随想录刷题| 多重背包理论基础、背包问题的总结
代码随想录刷题| 多重背包理论基础、背包问题的总结
代码随想录刷题| 多重背包理论基础、背包问题的总结
|
Java
青蛙跳台阶问题——动态规划求解(Java实现)
青蛙跳台阶问题——动态规划求解(Java实现)
253 0