zoukankan      html  css  js  c++  java
  • dp--背包

    背包问题

    01背包

    (n)个物品,每个物品都有一个价值和体积,有一个容量为(V)的背包,最大可以得到的价值是多少
    每个物品都有两种可能,选与不选

    code

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

    背包恰好装满

    定义(dp[i])表示(i)状态可达,初始化(dp)(0),代表不可达,(dp[0] = 1),代表可达
    状态转移方程(dp[i] = max(dp[i],dp[i-a[i]]))

    code

    for(int i = 1; i <= n; i++) 
    {
        for(int j = V; j >= a[i]; j++) 
        {
            dp[j] = max(dp[j],dp[j-a[i]]);
        }
    }
    

    完全背包

    每个物品可以取任意次,而不是一次,所以我们就不用担心(01)背包的状态覆盖问题
    直接从(a[i])遍历到(V)

    code

    for(int i=1; i<=n; i++)
    {
      for(int j=w[i]; j<=m; j++)       //和01背包的唯一区别
      {
          f[j]=max(f[j],f[j-w[i]]+v[i]);
      }
    }
    

    多重背包转01背包

    多重背包例题
    每个物品可以取(c)

    二进制优化

    我们把(c)次划分成(1,2,4,8...)之类的数,然后进行(01)背包就行了
    一定存在某个最优的次数,而划分成二进制一定可以表示成那个数

    code

    for(int i = 0,a,b,c; i < n; i++)
    {
        scanf("%d%d%d",&a,&b,&c);           //价值,重量,数量
        int k = 1;
        while(c-k > 0)
        {
            v[t] = k*a;
            w[t++] = k*b;
            c -= k;
            k *= 2;
        }
        v[t] = c*a;         //把剩下的当成一个物品
        w[t++] = c*b;
    }
    
    //01背包
    for(int i = 0; i < t; i++)  //t个物品
    {
        for(int j = m; j >= w[i]; j--)
        {   
            dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    

    单调队列优化

    二维背包

    增加一维就好了,dp[i][j][k] //第i个,花费j,时间k
    也可以空间优化,优化掉第一维度

    参考博客

    https://www.cnblogs.com/-guz/p/9866118.html

  • 相关阅读:
    MSSQL安全审计文件执行Rootkit-WarSQLKit
    组建自己的局域网服务器
    python openpyxl表格样式设置
    ssh 和 scp 命令访问非默认22端口。
    set | grep IFS
    Python: check if key exists in dictionary (6 Ways)
    在线Jinja2解析器
    FastApi教程|测试WebSockets
    QT Qstring的用法
    QT UI拖拽方法
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/11991339.html
Copyright © 2011-2022 走看看