• 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]);
    }
    
    
    
     
  • 相关阅读:
    Asp.net性能优化总结(一)
    Visual C#常用函数和方法集汇总
    ASP.net下大文件上传的解决方案及WebbUpload组件源码
    正则表达式学习
    在Asp.net中为图像加入版权信息
    Cognos 维度函数
    Cognos8.3函数使用手册(二)
    cognos更新步聚
    Cognos8.3函数使用手册(一)
    Cognos 8 报表备份和恢复
  • 原文地址:https://www.cnblogs.com/orion7/p/7490916.html
Copyright © 2020-2023  润新知