DP背包问题理解

DP分析

1、背包问题(选择问题)

在这里插入图片描述

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

2、要点分析

  • 特点:每个物品仅能使用一次

重要变量&公式解释

  • f[i][j]:表示所有选法集合中,只从前i个物品中选,并且总体积≤j的选法的集合,它的值是这个集合中每一个选法的最大值.(注意:这里的二维数组f可以把它看成是一个求最大值的函数,但是不用去实现。可看成函数两边左右抵消。便于理解可以直接把它当成最大值看待)
  • 状态转移方程:f[i][j] = max(f[i-1][j]f[i-1][j-v[i]]+w[i])
  • f[i-1][j]:不选第i个物品的集合中的最大值。
  • f[i-1][j-v[i]]+w[i]:选第i个物品的集合,但是直接求不容易求所在集合的属性,这里迂回打击一下,先将第i个物品的体积减去,求剩下集合中选法的最大值.
#include <iostream>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N][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++)
        {
            //未选第i个元素
            f[i][j] = f[i - 1][j];
            if (j >= v[i])
                f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
        }
    }
    cout << f[n][m] << endl;
    return 0;
}

3、理解思路

  • 第i个物品要么选,要么不选。在这里插入图片描述

  • 在一开始的时候自己对这个算法也是很迷,不清楚f[i][j]为什么能表示前i个物品的总体积小于j的总价值的最大值。后面才慢慢理解,在开始的时候可以看成存在这个求最大值的函数。int Fmax(int i , int j);(这里不用具体实现的细节),求出不包含第i个的最大值,和不包含第i个的最大值。取两者中的最大值就是所需。

  • for (int i = 1; i <= n; i++)
    for (int j = 0; j <= m; j++);这个循环中遍历了所有可能存在的结果的最大值。并把每一次结果的最大值放在二维数组中。最后f[n][m]表示所有物品中的最大值。直接输出。

  • 在这里我们把最大值结果的集合划分为两个部分。一、没选第i个物品的,最大值为前i-1个物品的价值的最大值f[i-1][j]。一、选了第i个物品的。由于选定了第i个物品,我们把第i个物品提取出来,那么前i-1个物品的最大值为f[i - 1][j - v[i]] ,最后再加上w[i]的价值。

猜你喜欢

转载自blog.csdn.net/qq_45372719/article/details/108726406