01背包问题
dp[i][j]表示的是要存放第i个物品时,背包此时的容量为j,背包内物品的总价值
weight表示物品占据背包的体积
dp[i][j]=(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);//状态转移方程
我们之前看的关于dp的问题,对于每一个元素的处理方法就是选和不选
我们的状态转移方程也是根据这个得出的
01背包问题动态规划模板:
void dp(){
for(int i=1;i<=number;i++){
for(int j=1;j<=capacity;j++){
if(j<w[i]){
v[i][j]=v[i-1][j];
}
else{
if(v[i-1][j]>v[i-1][j-w[i]]+v[i]){
v[i][j]=v[i-1][j];
}else{
v[i][j]=v[i-1][j-w[i]]+v[i];
}
}
}
}
}
总结:利用动态规划解决背包问题的效率即是填写此张表的效率,
所以动态规划的时间效率为O(number*capacity)=O(n*c),
由于用到二维数组存储子问题的解,所以动态规划的空间效率为O(n*c);
void FindWhat(int i,int j)//寻找解的组成方式
{
if(i>=0)
{
if(V[i][j]==V[i-1][j])//相等说明没装
{
item[i]=0;//全局变量,标记未被选中
FindWhat(i-1,j);
}
else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
{
item[i]=1;//标记已被选中
FindWhat(i-1,j-w[i]);//回到装包之前的位置
}
}
}
完全背包问题
完全背包是在01背包的基础上进行进阶的,01背包之所以在背包前加个01是因为物品每种只有一个,两种状态,放与不放,放就是1,不放就是0
完全背包比01背包多的条件是物品不止一个,会有多个物品,我们可以选择多个相同的物品放入背包
void packageTotal(){
for(int i = 1; i <= N; i++){
for(int j = 1; j <= M; j++){
if(weight[i] > j){ //如果重量比容量大,放不下,就不放
V[i][j] = V[i - 1][j];
}
else{ //其实 if跟else可以去掉的
int k = j / weight[i]; //如果能放下,要看看能放几个,然后放几个跟不放所有情况比一下看哪个价值最大,除法默认向下取,也可以用floor()
for(int m = 0; m <= k; m++){
if(V[i - 1][j - m * weight[i]] + m * value[i] > V[i][j])
{
V[i][j] = V[i - 1][j - m * weight[i]] + m * value[i];
}
}
}
}
}
}
背包问题相关优秀博文:
教你彻底学会动态规划——入门篇
动态规划三部曲之一个故事教你透彻理解动态规划(一)
https://blog.csdn.net/qq_38749759/article/details/77406397
https://blog.csdn.net/na_beginning/article/details/62884939
https://blog.csdn.net/m0_37907835/article/details/78991992