经典算法问题——01背包
Posted 哈拉泽空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典算法问题——01背包相关的知识,希望对你有一定的参考价值。
b站讲解视频
https://www.bilibili.com/video/BV1ob411C7gg?from=search&seid=9137415201994217470
首先第一点:明确dp[i][j]表达的含义:存放的是一共i个物品,所用容量为j时,最大的价值
递推关系式:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
if volume[i]>j
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
j
−
v
o
l
u
m
e
[
i
]
]
+
v
a
l
u
e
[
i
]
)
if volume[i]<=j
dp[i][j]= \\begincases dp[i-1][j] & \\textif volume[i]>j\\\\ max(dp[i-1][j],\\ \\ dp[i-1][j-volume[i]]+value[i]) & \\textif volume[i]<=j\\\\ \\endcases
dp[i][j]=dp[i−1][j]max(dp[i−1][j], dp[i−1][j−volume[i]]+value[i])if volume[i]>jif volume[i]<=j
解释:
-
i f v o l u m e [ i ] > j if \\ \\ volume[i]>j if volume[i]>j
意思是当前背包容量为j,第i个物品需要容量为volume[i]
那需要容量都比剩余容量大了,当然没法放进去啦!
-
i f v o l u m e [ i ] < = j if \\ \\ volume[i]<=j if volume[i]<=j
意思是需要容量小于剩余容量,当然可以放进去,但放不放还需要做一下取舍:
所以取放或不放的最大值
m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − v o l u m e [ i ] ] + v a l u e [ i ] ) max(dp[i-1][j],\\ \\ dp[i-1][j-volume[i]]+value[i]) max(dp[i−1][j], dp[i−1][j−volume[i]]+value[i])
code for HDU 2602
#include<cstring> #include<iostream> using namespace std; const int maxn=1005; int N,V; int weight[maxn],value[maxn],res[maxn][maxn]; int max(int a,int b) return a>b?a:b; void package() memset(res,0,sizeof(res)); for(int i=1;i<=N;i++) for(int j=0;j<=V;j++)//不必纠结这里是从0开始还是从1开始,从0开始是考虑了可能会有物品体积为0,但是价值不为0的情况(也就是这类物品随便放,反正不会站价值,这种情况要是从1开始,那岂不是错过了这些免费的物品?)根据具体题目而定 if(weight[i]>j) res[i][j]=res[i-1][j]; else res[i][j]=max(res[i-1][j],res[i-1][j-weight[i]]+value[i]); int main() int t; cin>>t; while(t--) cin>>N>>V; for(int i=1;i<=N;i++) cin>>value[i]; for(int i=1;i<=N;i++) cin>>weight[i]; package(); cout<<res[N][V]<<endl; return 0;
练习题
以上是关于经典算法问题——01背包的主要内容,如果未能解决你的问题,请参考以下文章