完全背包

完全背包:

题目描述:

有N中物品和一个容量是V的背包,每种物品都有无限多件可用。

有i种物品的体积是v[i] ,价值是 w[i].

求解将哪些物品装在背包,可使这些物品的总体积不超过背包容量,且总价值最大。

DP分析:

首先是朴素版本(二维完全背包) 时间复杂度:最坏是O(n^3)

#include<iostream>
#include<algorithm>

using namespace std;
const int N = 1010;
int f[N][N];
int n,m;
int v[N],w[N];
int main()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    cin >> v[i] >> w[i];
    for(int i = 1;i <= n;i ++)
    for(int j = 0;j <= m;j ++)
    for(int k = 0;k * v[i] <= j;k ++)
    f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
    cout << f[n][m] << endl;
    return 0;
}

提示:

这里分析的不包含第i个物品时为f[i - 1][ j ],但因为i从小到大遍历,则f[ i ][ j ]首先取自于后者,

则之后的赋值f[ i ][ j ]时用的都是当前i下的f[i - 1][ j ],也就是自己理解的滚动数组的原理

其余代码较为简单就不解释了,下面给出优化后的代码

完全背包问题(优化一:推导优化)时间复杂度O(n^2)

代码如下:

#include<iostream>
#include<algorithm>

using namespace std;
const int N = 1010;
int f[N][N];
int n,m;
int v[N],w[N];
int main()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    cin >> v[i] >> w[i];
    for(int i = 1;i <= n;i ++)
    for(int j = 0;j <= m;j ++)
    {
        f[i][j] = f[i - 1][j];
        if(j >= v[i])
        f[i][j] = max(f[i][j] , f[i][j - v[i]] + w[i]);
    }
    cout << f[n][m] << endl;
    return 0;
}

注释:

本次优化将k完全优化掉,将原来的f[ i ][ j ] 求值完全优化为 f[ i ][ j ] = max( f[i - 1][ j ] ,f[ i ][ j -v[ i ] ] + w[ i ]);

完全背包(优化二:一维数组优化)时间复杂度O(n^2)

#include<iostream>
#include<algorithm>

using namespace std;
const int N = 1010;
int f[N];
int n,m;
int v[N],w[N];
int main()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    cin >> v[i] >> w[i];
    for(int i = 1;i <= n;i ++)
    for(int j = v[i];j <= m;j ++)
    f[j] = max(f[j] ,f[j - v[i]] + w[i]);
    cout << f[m] << endl;
    return 0;
}

注释:本次优化仍然使用了滚动数组原理。

ps:第一次写完全背包笔记,希望各位聚聚批评指正QAQ

posted @ 2021-07-05 23:02  cust-bbtking  阅读(57)  评论(0编辑  收藏  举报