[动态规划] Charm Bracelet

描述

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;
}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值