• 动态规划的背包问题——01背包


    挺简单的,与完全背包差不多,只不过是所有的物品可以随便选改为了每个物品只能选一次

    状态设计(二维):设i为当前的物品,j为当前背包容量

    转移方程为f(i,j)=max{f(i-1,j),f(i-1,j-w[i])+v[i]} 其中w[i]为当前物品的重量,v[i]为当前物品的价值

    常规做法如下

    for(int i=1;i<=n;i++)//物品数
    {
        for(int j=0;j<=m;j++)//枚举容量 
        {
            if(j<w[i])//装不下肯定就不选
            {
                f[i][j]=f[i-1][j];
            }
            else//否则两种情况进行转移
            {
                f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
            }
        } 
    } 

    但这样空间复杂度为O(m*n),显然在m,n很大的情况下不得行

    所以我们可以采取优化

    我们看当前的最优解只与它的前一个有关,所以我们每次只更新这两个值即可

    法1 滚动数组优化

    int p=1,q=0;//只在这两行之间转移
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
             if(j<w[i])
             {
                 f[p][j]=f[q][j];
            }
            else
            {
                f[p][j]=max(f[q][j],f[q][j-w[i]]+v[i]);
            }
        }
        swap(p,q); //滚起来
    } 

    法2 一维状态转移

    通过观察还可以优化至一维f[n]表示当前容量下的最大值

    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=w[i];j--)
        {
            f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
    }

    可是你就会发现枚举容量的时候要倒序,这是为什么呢?

  • 相关阅读:
    电子工程师的血泪史
    最简单的bootloader的编写步骤
    6811汇编语言
    Tiny6410SHT10温湿度传感器
    Tiny6410裸机程序
    无线收发模块NRF24LU1和NRF24LE1
    转载工作10年的人总结的6句话
    Tiny6410取模软件设置
    别人的感悟
    在Windows下用Virtualbox虚拟linux时共享文件夹设置的方法
  • 原文地址:https://www.cnblogs.com/LJB666/p/10806103.html
Copyright © 2020-2023  润新知