ACM算法_背包小结

ACM算法_背包小结

01背包,完全背包,多重背包
模板
背包的基本模型就是给你一个容量为V的背包,在一定的限制条件下放进最多(最少?)价值的东西

  • 01背包
    01背包的基本模型就是有N件物品和一个容量为W的背包。(每种物品均只有一件)第i件物品的占重是w[i],价值是v[i]。求解将哪些物品装入背包可使价值总和最大。
        特点:每种物品仅有一件,可以选择放或不放。
        动态转移方程:
        - dp[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值。
        - dp[i-1][j]表示前i-1件物品恰放入一个容量为j的背包可以获得的最大价值。也就是,当前遍历到的物品不加入背包。
        - dp[i-1][j-w[i]]+v[i]表示前i-1件物品恰放入一个容量为(j-当前遍历到的物品重量)的背包可以获得的最大价值。也就是将当前遍历到的物品加入背包。至于把谁挤下去,在便利的过程中已经实现。
        dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
    
代码实现
    直接用二维数组dp[maxn][maxm];

关键代码

for(int i=1;i<=n;++i){//遍历物品
    for(int j=w[i];j<=W;++j){//遍历背包容量(因为动态转移方程里有对j-w[i]的访问,所以j从w[i]开始)
        dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
    }
}
    优化策略:由上可知,二维数组并不会交叉重复访问,因此可将二位数组优化为一维数组,将每次访问时变量的值当作i-1项的值,第二层遍历背包时,采用逆序,可保证,更新第i层的dp[j]前,dp[j]和dp[j-w[i]]储存的是第i-1层的值。

关键代码

for(int i=1;i<=n;++i){//遍历物品
    for(int j=W;j>=w[i];--j){//遍历背包容量(因为动态转移方程里有对j-w[i]的访问,所以j从w[i]开始)
        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    }
}
  • 完全背包
    完全背包的基本模型就是有N种物品和一个容量为W的背包,每种物品都有无限件可用。第i种物品的占重是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
        动态转移方程:
        dp[i][j]=max(dp[i][j],f[i-1][j-k*w[i]]+k*v[i])
        与01背包略有不同,完全背包是与当前背包状态比较的
    
代码实现
    直接用二维数组dp[maxn][maxm];

关键代码

for(i=1;i<=N;i++){
    for(j=0;j<=W;j++){
        for(k=0;k*w[i]<=j;k++)  
            dp[i][j]=max(dp[i][j],dp[i-1][j-k*w[i]]+k*v[i]);
    }
}
    优化策略:由01背包可将二位数组优化为一维数组可知,完全背包也能做类似优化,但由于比较的状态是当前状态,因此第二层遍历需顺序遍历

关键代码

for(i=1;i<=n;i++){
    for(j=need[i];j<=m;j++){
        if(j>=need[i])
            dp[j]=max(dp[j],dp[j-need[i]]+value[i]);
    }
} 
  • 多重背包
    多重背包的基本模型就是有N种物品和一个容量为W的背包。第i种物品最多有num[i]件可用,每件占重是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
    把物品拆开,把相同的num[i]件物品 看成 价值跟重量相同的num[i]件不同的物品,那么就转化成了一个规模稍微大一点的01背包了
        动态转移方程:
        dp[i][j] = max (dp[i-1][j],dp[i-1][j - k*weight[i]] +k*value[i] ) 
        还有其他效率更高的方法,能力有限,还不会-_-!!!
    
代码实现

关键代码

for(int i=1; i<=n; i++)//每种物品
    for(int k=0; k<num[i]; k++)//其实就是把这类物品展开,调用num[i]次01背包代码
        for(int j=m; j>=weight[i]; j--)//正常的01背包代码
            dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值