POJ3624--01背包

POJ3624–01背包

一、题目描述

Description
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 i in 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.
Input

  • 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
    Output
  • Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
    Sample Input
    4 6
    1 4
    2 6
    3 12
    2 7
    Sample Output
    23

二、解题思路

01背包。在这道题输入的数据有物品种类n、背包容量m、每个物品的容量v[i]、每个物品的价值d[i]。然后双层for循环实现操作,过程其实我也描述不太清楚,我就大概说一下,然后理解模板中的代码,之后参考模板多做题就可以自己写了。先拿第一个物品v=1,d=4,装进背包,那么背包里边的情况就是容量剩余5,价值是4(dp[1]=dp[2]=dp[3]=dp[4]=dp[5]=dp[6]=4),再装入第二个物品v=2,d=6,那么背包里边的情况就是容量剩余3,价值是10,(注意:这里再循环里边计算的时候在dp数组中是加了一种情况的,当背包中只有第二件物品时,背包容量剩余4,价值6,容量比之前大,这时刷新了之前dp[2]的值)经过这一轮刷新后结果为(dp[1]=4,dp[2]=6,dp[3]=dp[4]=dp[5]=dp[6]=10),依此类推。可见用语言描述这个过程是很复杂的,需要我们自己把这个背包容量变化的过程给理解透彻,只有这样我们才能够学会这个知识点。(个人建议把这个背包容量变化的过程通过循环输出出来,然后根据数据的变化去理解这个知识,我在参考代码里边把这个打印的代码给注释了,需要的同学可以用一下。)

三、参考代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define INT_MAX 1 << 30
#define MAX 100
typedef long long ll;
int n,m;
int v[3500];
int d[3500];
int dp[20000];
int f[3000][3000];

int main()
{
    memset(dp,0,sizeof(dp));
    scanf("%d%d",&n,&m);
    for (int i = 1; i <=n; i += 1)
    {
        scanf("%d%d",&v[i],&d[i]);
    }
    for (int i = 1; i <=n; i++)
    {
        for (int j = m; j >= v[i]; j--)
        {
            dp[j] = max(dp[j],dp[j-v[i]]+d[i]);
        }
    }
    /*for (int i = 1; i <=m; i++)
    {//这里其实就是最终的变化结果,想要看过程的可以看下边注释里边那个二维数组的打印过程。
        cout<<dp[i]<<' ';
    }*/

    printf("%d\n",dp[m]);
    /*memset(f, 0, sizeof f);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j < v[i]; j++)
            f[i][j] = f[i - 1][j];
        for(int j = v[i]; j <= m; j++)
        {
            if (f[i - 1][j] < f[i - 1][j - v[i]] + d[i])
                f[i][j] = f[i - 1][j - v[i]] + d[i];
            else
                f[i][j] = f[i - 1][j];
        }

    }
    for(int i=1; i<=n; i++)
    {//背包容量的变化过程
        for(int j=1; j<=m; j++)
        {
            cout<<f[i][j]<<' ';
        }
        cout<<endl;
    }
    cout << f[n][m] << "\n";*/
    return 0;
}

四、总结
刚开始学01背包的时候并不容易,动态规划本来就是比较抽象的知识,因为我们很难看透数据的变化,就像我们最开始学习递归的时候,就现在一些递归我还是不太理解的,可见我们需要不断地学习这些知识,当我们做题多了,思维开发的多了,这些知识自然而然地就理解了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值