acwing2. 01背包问题
题目描述
有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。
第 ii 件物品的体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
8
01背包
分析
对每件物品有两个选择
- 不选这个物品
- 当剩余容量大于此物品体积的时候,选择该物品
代码
二维代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1010;
int v[N], w[N];
int f[N][N];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
f[i][j] = f[i-1][j]; // 不选这个物品
if(j >= v[i]) f[i][j] = max(f[i][j], f[i-1][j-v[i]] + w[i]); // 选这个物品
}
}
printf("%d\n", f[n][m]);
return 0;
}
一维优化代码(具体为什么倒序枚举体积看参考文章)
简单说就是更新当前状态的时候用的是上一轮的状态,为了保证本轮状态更新一直用到的是上一轮的,所以从大到小枚举,可以使得更新时用到的小状态都是上一轮的
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1010;
int v[N], w[N];
int f[N];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &v[i], &w[i]);
}
for(int i = 1; i <= n; i++)
{
for(int j = m; j >= v[i]; j--)
f[j] = max(f[j], f[j-v[i]] + w[i]);
}
printf("%d\n", f[m]);
return 0;
}
时间复杂度
参考文章
一维动态规划的状态转移方程(
j
采取逆序的方式)
dp[j] = max(dp[j], dp[j - v[i]] + w[i])
其实两种做法,实现的思想是一样的,只不过一维数组更省空间,下面具体说说,为什么可以用一维数组来代替,而且要采取逆序的方式。
举例说明
假如枚举到:i = 3, j = 8, v[3] = 5, w[3] = 1
二维:dp[3][8] = max(dp[2][8], dp[2][3] + w[3]) 此时的dp[2][8]和dp[2][3]都是上一轮的状态值
一维:dp[8] = max(dp[8], dp[3] + w[3]) 我们要保证dp[8]和dp[3]都是上一轮的状态值
按照逆序的顺序,一维dp数组的更新顺序为:dp[8], dp[7], dp[6], ... , dp[3]
也就是说,在本轮更新的值,不会影响本轮中其他未更新的值!较小的index对应的状态是上一轮的状态值!
如果按照顺序进行更新,dp[3] = max(dp[3], dp[0] + w[0]),对dp[3]的状态进行了更新,那么在更新dp[8]时,用到的dp[3]
就不是上一轮的状态了,不满足动态规划的要求。
作者:polaris
链接:https://www.acwing.com/solution/content/3982/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix