完全背包详解--模板

优先理解01背包:

推导:

我们列举一下更新次序的内部关系:

f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w ,  f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....)
f[i , j-v]= max(            f[i-1,j-v]   ,  f[i-1,j-2*v] + w , f[i-1,j-3*v]+2*w , .....)
由上两式,可得出如下递推关系: 
                        f[i][j]=max(f[i,j-v]+w , f[i-1][j]) 



1.01背包和完全背包核心代码其实只有一句不同(注意下标)       

 f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);   //01背包

        f[i][j] = max(f[i][j],f[i][j-v[i]]+w[i]);   //完全背包问题


为什么完全背包变成了 i 呢,因为 每个物品都是可以随便选的,不像01背包只能选一次。
2.同样优化:
        核心代码:

for(int i = 1 ; i<=n ;i++)
    for(int j = v[i] ; j<=m ;j++)//注意了,这里的j是从小到大枚举,和01背包不一样
    {
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }

为什么从前往后枚举呢,因为与01背包反过来,要保证是当前 i 层更新的,而不是第 i-1 层更新过来的。

点击跳转例题
代码:
 

#include

using namespace std;

const int MAXN = 10000;
int v[MAXN];    // 体积 
int w[MAXN];    // 价值 
int f[MAXN][MAXN];  // f[i][j], j体积下前i个物品的最大价值 

int main() 
{
    int n;
    int m;  // 背包体积 
    cin >> n >> m;
    for(int i = 1; i <= n; i++) 
        cin >> v[i] >> w[i];

    f[0][0] = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 0; j <= m; j++) 
        {
            f[i][j] = f[i - 1][j];  // 不选第i个物品//集合一定存在; 
            //再次更新集合,看是否有更大的解;
            if(j >= v[i])           // 可以选择第i个物品,状态方程见上面推导    
                f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
        }

    cout << f[n][m] << endl;
    return 0;
}

你可能感兴趣的:(总结的语法,动态规划,计算机考研复试上机题,算法,c++,数据结构,蓝桥杯)