从递归到DP——01背包问题初探

目录

问题描述:

1.纯递归解决,容易溢出

2.记忆化搜索法

3.由记忆化搜索推导递推关系,使用动态规划法DP

备注:


问题描述:

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

 测试样例:
n=4,{w,v}={(2,3),(1,2),(3,4),(2,2)},W=5


4
2 3
1 2
3 4
2 2
5

1.纯递归解决,容易溢出

#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N=1000; 

int n,W;
int w[MAX_N],v[MAX_N];
int dp[MAX_N+1][MAX_N+1];//记忆化数组 

//从第i个物品开始挑选总重小于j的部分 
int rec(int i,int j){
	int res;//剩余物品 
	if(i==n){//已经没有剩余物品了 
		res=0; 
	}else if(j<w[i]){//无法挑选这个物品 
		res=rec(i+1,j);
	}else{//尝试挑选和不挑选两种情况 
		res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
	}
	//将结果记录在数组中 
	return res;
} 

int main(){
	
	//-1表示未计算过,初始化整个数组 
	memset(dp,-1,sizeof(dp));
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>w[i]>>v[i];
	}
	cin>>W;
	cout<<rec(0,W)<<endl;
	
	return 0;
} 

2.记忆化搜索法

#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N=1000; 

int n,W;
int w[MAX_N],v[MAX_N];
int dp[MAX_N+1][MAX_N+1];//记忆化数组 

//从第i个物品开始挑选总重小于j的部分 
int rec(int i,int j){
	if(dp[i][j]>=0){//如果已经计算过的话就直接使用之前的结果
		return dp[i][j]; 
	} 
	int res;//剩余物品 
	if(i==n){//已经没有剩余物品了 
		res=0; 
	}else if(j<w[i]){//无法挑选这个物品 
		res=rec(i+1,j);
	}else{//尝试挑选和不挑选两种情况 
		res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
	}
	//将结果记录在数组中 
	return dp[i][j]=res;
} 

int main(){
	
	//-1表示未计算过,初始化整个数组 
	memset(dp,-1,sizeof(dp));
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>w[i]>>v[i];
	}
	cin>>W;
	cout<<rec(0,W)<<endl;
	
	return 0;
} 

3.由记忆化搜索推导递推关系,使用动态规划法DP

#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N=1000; 

int n,W;
int w[MAX_N],v[MAX_N];
int dp[MAX_N+1][MAX_N+1];//记忆化数组 

int main(){
	
	//-1表示未计算过,初始化整个数组 
	memset(dp,-1,sizeof(dp));
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>w[i]>>v[i];
	}
	cin>>W;
	for(int i=n-1;i>=0;i--){
		for(int j=0;j<=W;j++){
			if(j<w[i]){
				dp[i][j]=dp[i+1][j];
			}else{
				dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
			}
		}
	} 
	cout<<dp[0][W]<<endl;
	
	return 0;
} 

备注:

1.递推关系可以有很多种,此题至少三种

2.memset用法:https://blog.csdn.net/qq_41895747/article/details/103898388

发布了228 篇原创文章 · 获赞 76 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41895747/article/details/103898847