描述
Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N(1 ≤ N≤ 3,402) available charms. Each charm iin the supplied list has a weight Wi(1 ≤ Wi≤ 400), a 'desirability' factor Di(1 ≤ Di≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M(1 ≤ M≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
输入
Line 1: Two space-separated integers: N and M
Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
输出
Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
样例输入
4 6 1 4 2 6 3 12 2 7
样例输出
23
解题分析
这是比较经典的零一背包问题,我们有一组物品,物品有自己的重量和价值,我们有一个背包,可以承受一定的重量,需要我们去计算出我们在限定的重量下所能得到的最大的价值。首先我们考虑一下dp[i][j]表示考虑前 i 个物品,背包承重为 j 的时候,我们所能得到的最大价值,那么,此刻我们去思考一下递推关系,首先我们采用一个分类讨论的思想,dp[i][j]=max{dp[i-1][j],dp[i-1][j-w[i]]+v[i]},就是说,我们对于第 i 个物品有两种选择,取或者不取,如果不取的话,那么我们只要考虑前 i-1 个物品,这个时候我们承重还是 j;反之,如果我们取了第 i 个物品,那么我们就需要在前 i-1 个物品中,以承重为 j - w[i] 去取一个最大值。考虑我们的递推公式,我们需要前面的一些数据,那么我们需要从前往后递推去更新dp数组。但是实际上本题还有一些更加优化的办法,因为我们注意到,我们只需要使用i 和 i-1 两个维度,也就是说我们不需要太多的维度,所以可以考虑采用滚动数组的方法,进一步减少我们的内存占用。但是,我们再仔细思考一下,其实还有一个更加优化的方法是使用一维数组,但是这个时候要格外地注意我们的更新的一个方向,首先,我们还是需要一个两层的循环作为一个更新的迭代次数,然后我们在第二维的时候,从后往前更新 dp 数组,j=W;j>=w[i];j-- ,然后递推公式选择dp[j] = max{dp[j],dp[j-w[i]]+v=[i]},最后直接输出dp[W]作为我们的答案即可。其中这个W表示我们背包的最多承重。
代码演示
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <map>
#include <stack>
int N,W[3405]={0},D[3405]={0};
int M;
int dp[12885];
using namespace std;
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
scanf("%d%d",&W[i],&D[i]);
}
for(int i=1;i<=N;i++)
for(int j=M;j>=W[i];j--){
dp[j]=max(dp[j],dp[j-W[i]]+D[i]);
}
printf("%d\n",dp[M]);
return 0;
}