背包学习笔记

简单递推

【A题】
之前好像讲过,找到递推关系就可以啦

注意

动态规划问题,必须满足最优化定理(一个最优策略的所有子策略也是最优的)&&无后效性定理(未来与过去没有关系)

01背包

题目

每种物品只有一个,选还是不选
每件物品有不同的体积和价值(每种只有一件),给出一定的体积,求最大的价值

Ⅰ 递归解法

  • 函数 K S ( i , j ) KS(i,j) KS(i,j):代表当前背包剩余容量为j时,前i个物品最佳组合所对应的价值

  • 有以下两种可能

    1. 背包剩余容量不足以容纳该物品
      此时背包的价值与前i-1个物品的价值是一样的, K S ( i , j ) = K S ( i − 1 , j ) KS(i,j) = KS(i-1,j) KS(i,j)=KS(i1,j)
    2. 背包剩余容量可以装下该商品,此时需要进行判断,因为装了该商品不一定能使最终组合达到最大价值
      ▶ 如果不装该商品,则价值为: K S ( i − 1 , j ) KS(i-1,j) KS(i1,j)
      ▶ 如果装了该商品,则价值为 K S ( i − 1 , j − w i ) + v i KS(i-1,j-wi) + vi KS(i1,jwi)+vi, 从两者中选择较大的那个,所以就得出了递推关系式

int ks(int i, int c) {
    int result = 0;
    if (i == 0 || c == 0)
     {
        // 初始条件
        result = 0;
    } 
    else if (ws[i] > c) 
    {
        // 超出体积,依次退回
        result = ks(i - 1, c);
    } 
    else 
    {
        // 可以放下
        int tmp1 = ks(i - 1, c);
        int tmp2 = ks(i - 1, c - ws[i]) + vs[i];
        result = max(tmp1, tmp2);
    }
    return result;
}

}

Ⅱ 动态规划解法

用一个二维数组用来存储中间结果,减少重复计算

int ks3(int i, int j) {
    // 初始化
    for (int m = 0; m <= i; m++) 
    {
        results[m][0] = 0;
    }
    for (int m = 0; m <= j; m++) 
    {
        results[0][m] = 0;
    }
    // 开始填表
    for (int m = 1; m <= i; m++) 
    {
        for (int n = 1; n <= j; n++) 
        {
            if (n < ws[m]) 
            {
                // 装不进去
                results[m][n] = results[m - 1][n];
            } 
            else 
            {
                // 容量足够
                if (results[m - 1][n] > results[m - 1][n - ws[m]] + vs[m]) 
                {
                    // 
                    results[m][n] = results[m - 1][n];
                } 
                else 
                {
                    results[m][n] = results[m - 1][n - ws[m]] + vs[m];
                }
            }
        }
    }
    return results[i][j];
}

完全背包

多重背包

你可能感兴趣的:(背包学习笔记)