本文以公式作为切入点,来帮助不理解公式的含义,或者不知道为什么使用该公式的来进行理解
本篇做以下保证:
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;
}