01背包问题——DFS/动态规划

问题概述:

有N件物品和一个容量为V的背包。第 i 件物品的价格(即体积,下同)是w[i],价值是c[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大,求最大价值。(1≤n≤20)

代码一:

(DFS:递归遍历,每种物品选和不选的两种结果,所有情况都遍历)

#include
using namespace std;
const int maxn=30;

int n,v,maxvalue=0;//物体的个数,背包容量,最大价值 
int w[maxn],c[maxn];//每件物品的重量和价值 
void dfs(int index,int sumw,int sumc){//当前处理的物品编号, 当前总重量,当前总价值 
	if(index==n){//出口条件为遍历完n件商品 
		if(sumw<=v&&sumc>maxvalue){
			maxvalue=sumc;//满足条件时更新最大价值 
		}
		return; //结束 
	}
	dfs(index+1,sumw,sumc);//不选第index件物品 
	dfs(index+1,sumw+w[index],sumc+c[index]);//选择第index件物品 
}

int main()
{
	scanf("%d%d",&n,&v);//物品个数和背包容量 
	for(int i=0;i

代码二:

1、代码一的进化版(节省了部分计算量)。

2、同样是DFS,但当目前总重量超过背包最大容量时,不再继续遍历(俗称“剪枝”)。

#include
using namespace std;
const int maxn=30;

int n,v,maxvalue=0;//物体的个数,背包容量,最大价值
int w[maxn],c[maxn];//每件物品的重量和价值
void dfs(int index,int sumw,int sumc) //当前处理的物品编号, 当前总重量,当前总价值
{

	if(index==n) //出口条件为遍历完n件商品 (能到达这里的一定是符合条件的)
	{
		return;
	}

	dfs(index+1,sumw,sumc);//不选第index件物品 (不用判断背包是否可容纳)

	if(sumw+w[index]<=v)
	{
		if(sumc+c[index]>=maxvalue)
		{
			maxvalue=sumc+c[index];//更新最大价值(最大价值不一定每次更新,当前物品重量为0时不更新) 
		}
		dfs(index+1,sumw+w[index],sumc+c[index]);//选择第index件物品
	}

}

int main()
{
	scanf("%d%d",&n,&v);//物品个数和背包容量
	for(int i=0; i

代码三:

(动态规划方法,时间复杂度和空间复杂度均为O(nV))

#include
#define maxn 1000
using namespace std;

int dp[maxn][maxn];//dp[i][v]表示前i件物品恰好装入容量为v的背包中所能获得的最大价值

int main()
{
	int n,V,w[maxn],c[maxn];//物品个数 背包总容量  每件物品的重量  每个物品的价值
	scanf("%d%d",&n,&V);
	for(int i=0; i

代码四:

(代码三的进化版,动态规划使用一维数组,空间复杂度可以达到O(V))

#include
#define maxn 1000
using namespace std;

int dp[maxn];

int main()
{
	int n,V,w[maxn],c[maxn];//物品个数 背包总容量  每件物品的重量  每个物品的价值
	scanf("%d%d",&n,&V);
	for(int i=0; i=w[i]; v--)//一维数组必须逆序 
		{
			dp[v]=max(dp[v],dp[v-w[i]]+c[i]);
		}
	}
	int ans=0 ;
	for(int v=0;v<=V;v++){
		if(dp[v]>ans){
			ans=dp[v];
		}
	} 
	printf("%d\n",ans);
	return 0;
}

 

你可能感兴趣的:(算法刷题笔记)