超基础详细的讲解用动态规划解决0-1背包问题,手写讲解版+各种语言代码(包含C、C++、Python、Java)

本文通过简化的方法介绍如何使用动态规划解决0-1背包问题,并提供了Python及C++实现代码,包括内存优化前后的时间对比。

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

本文以公式作为切入点,来帮助不理解公式的含义,或者不知道为什么使用该公式的来进行理解

本篇做以下保证:

1、保证以最简单的方法来进行讲解
2、保证各位在看完之后能简单地理解:动态规划解决0-1背包问题的操作方法
3、保证、。。。。

同时因为讲解过于详细基础,已经懂了“动态规划解决0-1背包”问题,但是想深度理解的建议划走

首先说明一下为什么手写,这是因为在我之前查找资料的时候,看到电子版的就烦,所以干脆自己分析了一遍,然后手写给各位分析一遍

上讲解:
(第一个公式,max中第一个‘+‘应该是’,‘)
在这里插入图片描述
在看完之后是不是对于各个式子的含义有了初步的理解,那么我们继续!!!
在这里插入图片描述
注:其实根据那个主公式是可以用递归的,但是受递归层数限制,性能会很差
代码以及详细的图文说明,我会在最近几天整理结束发布到该文章中

12.16号更新,抽空写了一下Python来代表以下思路,这样改成其他语言也比较简单了

# 内存优化前:
def doing(things, bag):
    start = time()
    dp = []
    for i in range(len(things)):
        dp_i = []
        for j in range(bag+1):
            if i > 0:
                result1 = dp[i-1][j]
                result2 = 0
                if j - things[i][0] >= 0:
                    result2 = dp[i-1][j-things[i][0]]+things[i][1]
                dp_i.append(max(result1, result2))
            else:
                if j - things[0][0] >= 0:
                    dp_i.append(things[0][1])
                else:
                    dp_i.append(0)
        dp.append(dp_i)
    print(max(max(dp)))
    end = time()
    print("优化前时间", end-start)


# 内存优化后
def doing1(things1, bag1):
    start = time()
    dp = []
    # 循环遍历物品
    for i in range(len(things1)):
        dp_i = []
        for j in range(bag1+1):
            if i > 0:
                dp = dp[-1:]
                result1 = dp[0][j]
                result2 = 0
                if j - things1[i][0] >= 0:
                    result2 = dp[0][j-things1[i][0]]+things1[i][1]
                dp_i.append(max(result1, result2))
            else:
                if j - things[0][0] >= 0:
                    dp_i.append(things[0][1])
                else:
                    dp_i.append(0)
        dp.append(dp_i)
    print(max(max(dp)))
    end = time()
    print("优化后时间:", end-start)


def test(numb):
    li = []
    thing_one = []
    for i in range(0, numb, 1):
        for j in range(2):
            thing_one = []
            w = random.randint(1, 9)
            v = random.randint(1, 9)
            thing_one.append(w)
            thing_one.append(v)
        li.append(thing_one)
    return li


if __name__ == '__main__':
    import random
    from time import *
    # numb_sum = int(input("数量"))
    # thing = test(numb_sum)
    # bag = int(input("容量"))
    # doing(thing, bag)
    numb_sum = [1000,2000,4000,8000,16000,32000,64000,128000,256000,512000]
    bag = [1000,5000]
    for main_i in bag:
        for main_j in numb_sum:
            print("数量:",main_j,"容量",main_i)
            thing = test(main_j)
            doing(thing, main_i)
            doing1(thing, main_i)


c++

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int  n,v;
    cin>>n>>v;
    vector<int> weight(n);
    vector<int> value(n);
   	//0-v的长度,因此是v+1个
    vector<vector<int>> dp(n,vector<int>(v+1,0));
    //输入重量和价值
    for(int i=0;i<n;i++){
        cin>>weight[i]>>value[i];
    }
    //第一行【0-第一个物品重量前】均是0
    for(int j=weight[0];j<=v;j++){
        dp[0][j] = value[0];
    }
    for(int i=1;i<n;i++){
        for(int j=0;j<=v;j++){
			// 减去新加入物品后的背包容量小于0时,拒绝加入,直接等于前i-1个物品产生的最大价值
            if(j-weight[i]>=0){
               	// 动态规划方程
                dp[i][j] = max(dp[i-1][j],value[i]+dp[i-1][j-weight[i]]);
            }else{
                dp[i][j] = dp[i-1][j];
            }
        }
    }
        cout<<dp[n-1][v]<<endl;

    return 0;
}

c++内存优化

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int  n,v;
    cin>>n>>v;
    vector<int> weight(n);
    vector<int> value(n);
    vector<int> dp(v+1,0);
    
    for(int i=0;i<n;i++){
        cin>>weight[i]>>value[i];
    }
    for(int j=weight[0];j<=v;j++){
        dp[j] = value[0];
    }
    for(int i=1;i<n;i++){
        for(int j=v;j>=0;j--){
            if(j-weight[i]>=0){
                dp[j] = max(dp[j],value[i]+dp[j-weight[i]]);
            }
        }
    }
    cout<<dp[v]<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值