01背包 完全背包混讲(未写完)

蹲街弑〆低调 提交于 2019-12-19 15:34:59

---emmm想写几篇关于背包的,先说一下自己对01背包和完全背包的理解,望大佬指教。
//emm这是重写的,原稿由于电脑死机,一节课写的东西都没有了...
先介绍一下我同位wst..我以后博客中应该都会拿他举栗子..已得到本人允许 写这篇博客前扯点废话(违心的夸一下wst)...
wst是一个
冰肌玉骨 冰姿玉骨 冰肌雪肤 才貌双全 才貌兼全
才貌两全 才貌双绝 沉鱼落雁 齿白唇红 齿如含贝
齿如齐贝 齿若编贝 出水芙蓉 初发芙蓉 唇红齿白
豆蔻年华 蛾眉皓齿 耳顺之年 二八佳人 二八美人
粉白黛黑 粉白黛绿 粉白墨墨 芙蓉出水 国色天香
国色天姿 鹤发童颜 花容月貌 花容玉貌 花颜月貌
炯炯有神 绝代佳人 绝世佳人 络腮胡子 落雁沉鱼的学霸

擅长 唱 跳 打篮球..(本人自己说的)
其实wst还有一个职业(情节需要) 他是一个神偷 他有几个神奇的背包 接下来我要介绍他第一个背包 01背包
有一个黑心商店 他的商品如下

编号 重(W) 价(v)
0 2 3
1 3 4
2 4 5
3 5 8
4 9 10

wst是一个数学天才,他喜欢做事情做到最好
而且喜欢列式子 现在他的01背包w(容量)=20
他设了 一个B,B表示总价值,设了两个参数k,w
B(K,W) k表示前k个物品,w表示剩下的容量
什么意思呢
~~举个例子B(2,20)当他物品剩余量为20时,
他可以选择编号0~2的物品,并要得到最佳答案
很多动态规划问题都可以归到背包中
听不懂? 我们再讲的清楚一点
假如wst 要偷0~4的物品 当他偷完0~3
w=20-(2+3+4+5)=6 第4件太重容量不够,所以他就不能拿(废话..)
wst想了想便列了一个方程
B(k-1,w) 第k件太重,他只能偷k-1件
他又想了想如果第k件不会太重的话,机会就来了这里就会有两种选择
max{偷:B(k-1,w-wk)+vk//wst偷了k-1件,现在空间变成了w-wk,但是价值会加vk
不偷:(k-1,w)//和太重情况一样

再说明一下01背包
有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?(https://www.acwing.com/problem/content/3/

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int  N=1000+10;
int f[N][N];
int n,m;
int v[N],w[N];//太菜了..把v,w定义成二维了...
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=0;j<=m;j++)
        {
            f[i][j]=f[i-1][j];//第i个不选
            if(j>=v[i])
            f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
        }
        int res=0;
        for(int i=0;i<=m;i++)  res=max(res,f[n][i]);
        cout<<res<<endl;
        return 0;
}

由于wst比较懒,懒得多写字,他想了想自己应该可以优化一下这个方程。
//这里参考了一下(https://www.acwing.com/blog/content/124/
首先,wst回顾了一下dp的定义,以及如何使用
1.状态数组如何定义
2.阶段是什么
3.决策是什么
4.边界是什么
5.状态转移方程
f[i−1][j]就是前i-1个物品,花费j个容量的最大利润,在这里我们可以理解为,不选取第i个物品(即选取前i-1个)的最大利润.
f[i][j−v[i]]+w[i]就是选取第i个物品,花费为j个容量的最大利润,那么为什么要这么写?
因为我们要放入这个物品,那么至少我们得需要v[i]个容量,所以我们只能从j−v[i]这个容量推过来,不然我们放不下这个背包.
+w[i]很明显就是选取了这个物品,当然要将这个物品的价值加上去.
我们应该如何去优化他呢,答案是滚动数组//但这里介绍的一维数组
*/
//需要讲一下如何优化 将 二维压缩

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int  N=1000+10;
int f[N];
int n,m;
int v[N],w[N];//
 int main()
{//1.将二维 变成一维  优化  2.没必要循环  答案其实就是fm
    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=m;j>=v[i];j--)//这里发生了变化 因为 f[i]没有被算过 
        {
            //将不能再判断 why?思考一下 
            f[j]=max(f[j],f[j-v[i]]+w[i]);//二维变一维 
        }
        //int res=0;
        //for(int i=0;i<=m;i++)  res=max(res,f[n][i]);
        cout<<f[m]<<endl;
        return 0;
}

//初始化 不只把f[0] 变成0 所有都变成 0了 f[m] 表示所有体积小于等于最大价值是多少而不是恰好等于
//k<m f[k]=max_w; k 是从f[0] 一步一步转移过来的 ..后面先咕咕咕掉过几天贴

完全背包

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;
const int N=1010;
int n,m;
int f[N];
;int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
      {
        int v,w;
        cin>>v>>w;
        for(int j=v;j<=m;j++)
         f[j]=max(f[j],f[j-v]+w);
      }
      cout<<f[m]<<endl;
      return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!