Excaliburer`s Zone

It was challenging, but not risky.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1.0-1背包的朴素形式

0-1背包问题:给定编号为1,2...n的n个物品和一个容量为C的背包;每个物品的重量为$w_i$,每个物品的价值为$v_i$,求将物品装入背包后,背包能获得的最大价值。其状态转移方程为:

$$ dp[i][j] = \begin{cases} \max\{dp[i-1][j],dp[i-1][j-w_i] + v_i\} ,& {j ≥ w_i} \\ dp[i-1][j] , & {j < w_i} \end{cases} $$

其中dp[i][j]表示把编号为从1到i的i个物品放入容量为j的背包所得到的最大的价值。其实现代码如下:

 

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std;
/*0-1背包的朴素形式*/

int main()
{
    int n,C;//n为物品的个数,C为背包的容量
    int weight[MAX_NUM];
    int val[MAX_NUM];
    int dp[MAX_NUM][MAX_NUM];
    cout<<"输入物品个数和背包容量:"<<endl;
    cin>>n>>C;
    cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl;
    for(int i = 1; i <= n; i++)
        cin>>weight[i]>>val[i];
    memset(dp,0,sizeof(dp));//初始化dp数组
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= C; j++) //此处j的初值也可以为weight[i]开始,其实这样效率更高;不过为了便于理解才写成从1开始
        {
            if(j < weight[i])
                dp[i][j] = dp[i- 1][j];
            else
                dp[i][j] = max(dp[i - 1][j],dp[i-1][j - weight[i]] + val[i]);
        }
    cout<<"背包的最大价值为:"<<dp[n][C]<<endl;
}

 

这种朴素形式的0-1背包的算法的时间复杂度为O(n*C),空间复杂度也为O(n*C)。

 2.对0-1背包进行优化

对0-1背包的优化主要体现在空间复杂度的优化上,时间复杂度无法再优化了。可以参考:https://blog.csdn.net/hearthougan/article/details/53869671 或者 https://blog.csdn.net/yoer77/article/details/70943462 

或者 https://www.cnblogs.com/fengziwei/p/7750849.html 。

 

其实现代码如下:

 

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std;
/*0-1背包的优化形式*/

int main()
{
    int n,C;//n为物品的个数,C为背包的容量
    int weight[MAX_NUM];
    int val[MAX_NUM];
    int dp[MAX_NUM];//变成了一位数组
    cout<<"输入物品个数和背包容量:"<<endl;
    cin>>n>>C;
    cout<<"分别输入这"<<n<<"个物品的重量和价值:"<<endl;
    for(int i = 1; i <= n; i++)
        cin>>weight[i]>>val[i];
    memset(dp,0,sizeof(dp));//初始化dp数组
    for(int i = 1; i <= n; i++)
        for(int j = C; j >= 1; j--) //此处j的初值变成了C,然后递减;与朴素形式调过来了;当然此处的中止条件也可为j >= weight[i]
        {
            if(j < weight[i])
                dp[j] = dp[j];
            else
                dp[j] = max(dp[j],dp[j - weight[i]] + val[i]);
        }
    cout<<"背包的最大价值为:"<<dp[C]<<endl;
}

 

优化后的0-1背包算法,时间复杂度仍为O(n*C),空间复杂度变成了O(C)。

 

posted on 2018-07-19 15:49  Excaliburer  阅读(315)  评论(0编辑  收藏  举报