背包九讲hhhhhhhh

1.一件物品只有两种选的情况
2.每件物品可以选无限件
3.每件物品可以选的不同
4.
5.两种限制
6.每组只能选一件
7.求方案数
8.记背包问题最优的怎么选的方案
9.选一件物品,要选依赖性的,有一定的限制

1.01背包问题

每件物品只能用一次

体积从大到小枚举

2. 01背包问题 - AcWing题库

dp类似类似递推问题(如斐波那契数列),找递推公式

暴力做,dfs,2的N次方,用dp优化
朴素版(二维dp)
有限集合的最值问题
1.状态表示
    1.描述的集合是什么(所以之考虑前i个物品并且总体积不超过j的选法的集合)
    每个条件代表一个维度f[i][j]
    2.属性:f[i][j]的值(集合每个方案的属性,题目要求的)
2.状态的计算
    1.集合的划分,找最后一个不同点
        1.所有不选第i个物品的方案
            所有从1~i-1个物品里选择
            f[i][j]==f[i-1][j]
        2.所有选第i个物品的方案(最后必然包括物品i)
           j>=v[i] 变化的部分+不变的部分
           j<v[i] 是空的,不放第i个物品
            f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])

注意初始化是最开始的特殊情况,什么都不考虑的情况下,或者是数列里的a1

优化
从空间,时间上
二维到一维
f[i]这一层只用到上一层f[i-1],要么是用自己要么是用比自己小的
for(int i=1;i<=n;i++)
for(int j=vs;j>=v[i];j--)
f[i][j]=max(f[j],f[j-v[i]]+w[i])
j从大到小保证j-v[i]是在第i-1层更新的,不是第i层

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int v[N],w[N];
int f[N];
//因为用的i,j都是一侧的不是两侧的,所以可以用一维计算
int n,vs;
int main(){
    scanf("%d%d",&n,&vs);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&v[i],&w[i]);
    }
    for(int i=1;i<=n;i++){
        for(int j=vs;j>=v[i];j--){
            f[j]=max(f[j],f[j-v[i]]+w[i]);
        }
    }
    printf("%d\n",f[vs]);
    return 0;
}

 2.完全背包

每件物品可以用多次

体积从小到大循环

3. 完全背包问题 - AcWing题库

循环正向是因为,f[i][j-v]可以已经被更新过(里面已经包含了若干第i件物品)

证明可以用数学归纳法

体积循环一维空间有限制,二维空间无限制

//f[i][j]//i可以选i种物品,j当前背包的容量
#include<iostream>

using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
    {
        //朴素版
         for(int j=v[i];j<=m;j++){
        //     for(int k=0;k*v[i]<=j;k++){
        //         f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);

            // }
        //优化n*n
        // f[i][j]=f[i-1][j];
        // if(j>=v[i])f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);
        //优化空间n
        f[j]=max(f[j],f[j-v[i]]+w[i]);
         //01背包从大到小循环,因为01背包需要的是第i-1层的状态,但是到f[i][j]时前面的第i-1层已经被更新为第i层

         }
    }
    cout<<f[m]<<endl;
    return 0;
}

??????初始化,哔哩哔哩证明没懂,正好是f[m],则初始化要f[0],f[]=负无穷

不用正好f[m],初始化不止把f[0]=0,所有f[i]=0,转移最开始不一定是从f[0]转移过来,可以从任意一个数转移过来,当用不完背包总容量,还剩k个,就可以从f[k]转移,那一定可以和最优解一样的体积,

3.多重背包问题

每件物品有个数限制

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值