码迷,mamicode.com
首页 > 编程语言 > 详细

【动态规划】【C/C++】简单的背包问题

时间:2020-01-20 22:52:57      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:复杂度   维数   span   简单的   空间复杂度   size   大神   color   二维   

简单的背包问题

背包问题动态规划中非常经典的一个问题,本文只包含01背包,完全背包和多重背包。更加详尽的背包问题的讲解请参考崔添翼大神的《背包九讲》

简单的01背包

  • 问题导入:新年到了,mjl马上就要外出旅游。mjl拥有一个容量为P的小背包,他希望在自己的n件体积为Vi的物品中带走的物品体积之和尽可能的多,他最多能带走多少物品?(每件物品只有一个)
  • 问题分析:可以创建一个二维数组dp[i][j],使用0和1表示对于前i件物品是否能凑出j的体积。要判断dp[i][j]的值是否为true,可以查看dp[i-1][j-V[i]]即前i-1件物品是否能凑出j-V[i]的重量出来或者dp[i-1][j]即前i-1件物品已经可以把体积j凑出来。
  • 代码实现:
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1; i<=n; i++)
    {
        for(int j=p; j>=v[i]; j--)
        {
            if(dp[i-1][j-v[i]] || dp[i-1][j]) 
                {
                    dp[i][j] = 1;
                }
        }
    }
    int ans;
    for(int i=p; i>=0; i--)
    {    
        if(dp[n][j])
        {
            ans = j;
            break;
        }
    }

注意代码中从后向前更新dp[i][j],是为了防止一件物品被使用多次

对于简单01背包问题的优化

显然,在简单01背包问题中,空间复杂度达到了O(n*p)之多。而在每一次更新第i行的数据时,只需要i-1行的数据即可,再向上的数据完全可以舍弃,所以只需要开一个两行的二维数组即可。

01滚动:

  • 只存在第0行和第一行,每次更新数据后将第1行的数据复制到第0行
  • 代码实现:
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    for(int i=1; i<=n; i++)
    {
        for(int j=p; j>=v[i]; j--)
        {
            if(dp[0][j-v[i]] || dp[0][j]) 
            {
                dp[1][j] = 1;
            }
        }
        for(int i=0; i<=n; i++) 
        {
            dp[0][i] = dp[1][i];
        }
    }
    int ans;
    for(int i=p; i>=0; i--)
    {
        if(dp[1][j])
        {
            ans = j;
            break;
        }
    }

未完待遇……

【动态规划】【C/C++】简单的背包问题

标签:复杂度   维数   span   简单的   空间复杂度   size   大神   color   二维   

原文地址:https://www.cnblogs.com/sdutzxr/p/12219567.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!