zoukankan      html  css  js  c++  java
  • DP 01背包问题

      01 背包问题

      有n个重量和价值分别为wi和vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中总价值总和的最大值。

      这是被称为背包问题的一个著名的问题。01 背包是背包问题的其中一种,对于任意一个物品,可以选择0个(不选)和1个。

     dp[i+1][j]表示从0到i这i+1个物品中选出总重量不超过j的物品时总价值的最大值。
    我们可以得出如下的递推关系式

       首先 dp[0][j]=0
        dp[i+1][j]=dp[i][j]  (j<w[i])
        dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i])  (其他)
    void solve()
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<=W;j++)
            {
                if(j<W[i])
                    dp[i+1][j]=dp[i][j];
                else
                    dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]);
            }
        printf("%d
    ",dp[n][W]);
    }

    其实我们还可以讲两个数组滚动使用来实现重复使用。例如

    dp[i+1][j]=max(dp[i][j],dp[i+1][j-w[i]]+v[i])

    这一递推式中,dp[i+1]计算时只需要dp[i]和dp[i+1],所以可以结合奇偶性写成如下形式:

    int dp[2][maxw];
    void solve()
    {
        for(int i=0;i<n;i++)
            for(int j=0;j<=W;j++)
            {
                if(j<w[i])
                    dp[(i+1)&1][j]=dp[i&1][j];
                else
                    dp[(i+1)&1][j]=max(dp[i&1][j],dp[(i+1)&1][j-w[i]]+v[i]);
            }
        printf("%d
    ",dp[n&1][W]);
    }
    当n很大时,就可以节省很多空间。

    还可以这么写,只用一维数组,不过我觉得没上面那个好理解,不具有通适性。
    void solve()
    {
            for(int i=0;i<n;i++)
                for(int j=W;j>=w[i];j--)
                {
                    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
                }
        printf("%d
    ",dp[W]);
    }
    
    
    
     
  • 相关阅读:
    yii源码五
    yii源码四
    yii源码三 -- db
    yii源码二 -- interfaces
    yii源码一 -- CComponent
    jquery效果 窗口弹出案例
    JS滚动条
    JS表单验证
    [TCP/IP] TCP流和UDP数据报之间的区别
    [TCP/IP] 关闭连接后为什么客户端最后还要等待2MSL
  • 原文地址:https://www.cnblogs.com/orion7/p/7490916.html
Copyright © 2011-2022 走看看