Knapsack 2

QLU 1th Winter Training D

Problem Statement:

有 $N$ 个物品,编号为 $1, 2,\ldots,N$。对于每个 $i$($1\leq i\leq N$),物品 $i$ 的重量为 $w_i$,价值为 $v_i$。 - 太郎决定选择一些物品,并将它们放入背包带回家。背包的容量为 $W$,这意味着所选物品的重量总和必须至多为 $W$。

找出太郎带回家的物品价值的最大可能总和。

Constraints:

输入中的所有值都是整数

$1 \leq N \leq 100$

$1 \leq W \leq 10^{9}$

$1 \leq w_i\leq$ $W$

$1 \leq v_i\leq 10^{3} $

Input

输入以以下格式从标准输入给出:

N W

w1 v1

w2 v2

:

wN vN

Output

打印太郎带回家的物品价值的最大可能总和。

Solving

不同于传统的0-1背包问题,我们注意到此题所给的关于W的数据范围最高可达1E9,传统的以背包容量为主体变量的动态规划方程肯定会爆,我们同时也注意到所给的价值范围仅有1E9,所以我们可以转换思维以V作为我们动态规划的主体。

$$ Dp[j] = min(Dp[j],Dp[j-v[i]]+w[i]) $$

其意义为拿取总价值为 J 的物品所需要的最小空间

最后只需要逆向遍历Dp数组寻找第一个小于W空间的价值,其就为所求答案。

以下是用C++编写的程序代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;
const int N = 101;
const int MAXV = 100000; //1000(MAXVi) * 100(MAXN) 
int w[N],v[N];
int n,m;
int main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);
    cin >> n >> m;
   	for(int i=1;i<=n;i++)
    {
        cin >> w[i] >> v[i];
	}
    int dp[MAXV+1];// 拿取总价值为 i 的物品所需要的最小空间
    memset(dp,0x3f,sizeof(dp));
    dp[0] = 0;//不要忘记初始化Dp数组
    for(int i=1;i<=n;i++)
    {
        for(int j=MAXV;j>=v[i];j--)
        {
			dp[j] = min(dp[j],dp[j-v[i]]+w[i]);		            
	   	}
	}
    for(int i = MAXV;i;i--)
    {
        if(dp[i]<=m)
        {
        	cout << i;
        	break;
    	}
    }
    return 0;
}
Licensed under CC BY-NC-SA 4.0
Member of the Qilu University Of Technology ACM-ICPC Association
Built with Hugo
Theme Stack designed by Jimmy