01背包

本文详细介绍了01背包问题,这是一种经典的动态规划问题。内容包括01背包的基本概念,它表示每种物品仅有一件,可以选择放或不放。核心思路是通过状态转移方程`f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}`来求解最大价值。文章提供了二维和一维动态规划的实现代码,并指出一维优化的方法是由于可以倒序处理,从而节省空间。" 118539479,10037570,NET高级班:Redis分布式缓存与ServiceStack String类型实践,"['.NET高级开发', 'Redis缓存', 'ServiceStack框架', '分布式存储', '秒杀系统']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01背包


背包有背包9讲,现在比较熟悉的就是01背包了,01背包的问题就是选或不选,那么用的就是动态规划(暂时还没有体验到这个特点。)

01 背包本质: dp[i][j] : 表示 第i行的最大的价值,现在的容量能装最大的价值。
变成一维的时候,从大的往小的放,缩小一维空间

现在就来讲一讲:
01背包:
题目
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
基本思路
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
这个式子很重要,基本的思路就是这样。
1.二维:二维很方便,基本上就是一个二维VN数组,

长度V
N
Phone$12
Pipe$1

代码如下:这里给出第一行开始填,也可以最后一行开始填

#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

struct  package
{
    int w;//价值
    int v;//容量
};


int main()
{
    package bag[100];
    int n, m;
    int s[101][101];
    cin >> n >> m;
    for (int i = 0; i <= n; i++)
        s[i][0] = 0;
    for (int i = 0; i <= m; i++)
        s[0][i] = 0;
    //不知道为什么,一定要把上面的两个for语句写上,否则结果就会出现问题。
    for (int i = 0; i < n; i++)
    {
        cin >> bag[i + 1].v >> bag[i + 1].w;
    }
    int d = min(bag[1].v, m);
    for (int i = 0; i < d; i++)
        s[1][i] = 0;

    for (int i =d; i <= m; i++)
        s[1][i] = bag[1].w;
    for (int i = 2; i < n; i++)
    {
        for (int j = 0; j < bag[i].v; j++)
            s[i][j] = s[i - 1][j];
        for (int j = bag[i].v; j <= m; j++)
            s[i][j] = max(s[i - 1][j], s[i - 1][j - bag[i].v] + bag[i].w);
            //这里需要前面的初始化。当j=beg[i].v时,就是s[i-1][0]初始化。
    }
    if (bag[n].v > m)
        s[n][m] = s[n - 1][m];
    else
        s[n][m] = max(s[n - 1][m], s[n - 1][m - bag[n].v] + bag[n].w);
    printf("%d\n", s[n][m]);
    system("pause");
    return 0;
}

上面的思路的是先将第一行填好,然后下一行根据上一行:
简单说就是:s[i]]n] 取决于s[i-1][n],和s[i-1][n-w]。
用过之后就就可以丢掉了,这就是为什么优化可以用一维来替换二维。
下面是一维代码:

//这里描述将二维压缩成一维背包
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

struct  package
{
    int w;
    int v;
};

int main()
{
    package bag[1000];
    int goal[1001];
    int n, c;
    cin >> n >> c;
    for (int i = 1; i <= n; i++)
    {
        cin >> bag[i].w >> bag[i].v;
    }
    goal[0] = 0;//这里就相当于一维数组的初始化,将0行0列的初始化为0;
    memset(goal, 0, sizeof(goal));
    for (int i = 1; i <= n; i++)
    {
        for (int j = c; j >= bag[i].w; j--)
            goal[j] = max(goal[j], goal[j - bag[i].w] + bag[i].v);
    }
    //这里分析为什么可以将二维压缩成一维,主要是将前面的s[i-1],[i]去掉了。
    //同时必须要倒序,因为后面的数组的值是根据前面的s[j-w],s[j],如果正序
    //就会先填s[j-w],导致错误
    printf("%d\n", goal[c]);
    system("pause");
    return 0;
}

用一维的过程和二维差不多,就是必须要倒序,原因如上。二维就是那种随便填的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值