算法—动态规划(2)0-1背包问题回顾

算法—动态规划(2)0-1背包问题回顾

0-1背包问题应该算是我本人第一个接触的dp问题,不过当时确实是没弄懂。今天重新回顾了一下,不禁又有了新的收获

问题描述

n个物品,重量和价值分别为 w i w_i wi v i v_i vi,背包总的承重力为W,求能装入的最大价值。

问题分析

相比起一维dp,这里的问题变成了二维的:我要求的是价值,但我又不得不考虑重量的限制。
我们先来考虑一下边界状态:
1) w i > W w_i>W wi>W,那么很明显,直接GG,装不了;
2) ∑ w i < W \sum w_i <W wi<W,那么都可以装;
好,这两种边界状态下,那么第一个是0;第二个是求和。
那么正常的转态下呢:
我们设函数 d p ( i , j ) dp(i,j) dp(i,j)表示:当总重量小于j时(也就是说背包还可以装),从下标为i的商品开始挑选,得到的商品的最大值。
我们都知道,dp问题就是一个在动态中“选or不选”的问题。前面已经提到了,如果单件商品重量大于承重范围,那就直接不选了,跳过下一个;如果符合要求,那就看当前这一物品的选入是否比下一物品的选入更有价值。
即状态转移方程如下:
d p ( i , j ) = d p ( i + 1 ) ( j ) j < w [ j ] dp(i,j)=dp(i+1)(j) j<w[j] dp(i,j)=dp(i+1)(j)j<w[j]
d p ( i , j ) = m a x [ d p ( i + 1 , j ) , d p ( i + 1 , j − w [ j ] − v [ i ] ) ] dp(i,j)=max[dp(i+1,j),dp(i+1,j-w[j]-v[i])] dp(i,j)=max[dp(i+1,j),dp(i+1,jw[j]v[i])]
解释一下该方程:
第一行意为:此时重量是符合的,那我就放进去;
第二行:此时重量符合,承重余量面临不足,那么我就考虑了:是放进去还是不放进去,跳过看下一个?
由于j表示放,那么j-w[i]-v[i]就表示不放。
在此我们还有个问题?我们是否需要全部搜索一遍?其实不必,已经搜索过的,就可以跳过。
那么下面来看一下代码:

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxN=3405;
const int maxW=405;
int dp[maxN][maxW];
int N,W;
int w[maxW],v[maxN];
int rec(int i,int j){    
    if(dp[i][j]>=0) return dp[i][j];//记忆化搜索,搜过的就变成正数了。初始化为-1是防止特殊情况出现
    int ans;
    if(i==N) ans=0;//超重,一个都放不了
    else if(j<w[i]) ans=rec(i+1,j);//能放,一直放
    else ans=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);//要开始挑了
    return dp[i][j]=ans;
}
int main(){
    memset(dp,-1,sizeof(dp));
    cin>>N>>W;
    for(int i=0;i<N;i++)
    {
        cin>>w[i];
        cin>>v[i];
    }
    int res=rec(0,W);
    cout<<res<<endl;
    return 0;
}
}

总结

0-1背包问题相比入门级别的dp问题,扩展到了二维,即“目标”是一个维度,而限制条件又是另一个维度的事。因此在考虑问题的同时,要更加注重临界转态。另外,在考虑搜索问题的同时,又要注意减枝问题,可采用对数组统一初始化的思路。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值