算法笔记---DFS--背包装入的最大价值问题P273

目录

算法笔记---DFS--背包装入的最大价值问题P273

深搜

代码:

运行结果:

改进

代码:

运行结果:


算法笔记---DFS--背包装入的最大价值问题P273

深搜

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=30;

int n,V,maxValue;
int w[maxn],c[maxn];

void dfs(int index,int sumW,int sumC){
	if(index==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<n;i++) scanf("%d",&w[i]);
	for(int i=0;i<n;i++) scanf("%d",&c[i]);
	
	dfs(0,0,0);
	
	printf("%d",maxValue);
	 
	return 0; 
} 

运行结果:

(未采用剪枝策略的深度优先搜索)存在以下主要缺点:

  1. 无用搜索: 代码没有实施任何剪枝策略,这意味着在递归过程中,即使后续选择可能导致总重量超过背包容量,程序仍然会尝试选择当前物品并继续进行递归。这导致了大量的无用搜索,即探索了许多不可能构成有效解的状态(即总重量超过背包容量的物品组合),浪费了计算资源。

  2. 效率低下: 由于缺乏剪枝,算法在处理具有大量可行解的问题实例时,尤其是当物品数量较大或背包容量相对较小时,会面临非常大的搜索空间。在这种情况下,算法的时间复杂度可能是指数级别的,即随着物品数量的增长,所需计算时间呈爆炸性增长,导致算法在实际应用中可能无法在合理时间内找到解。

  3. 内存消耗: 深度优先搜索通常伴随着较深的递归栈,特别是在没有剪枝的情况下。当递归层次很深时,可能会耗尽可用的栈空间,导致程序崩溃。虽然这个问题在本例中可能不如时间复杂度问题突出,但对于某些特定的输入数据或在资源有限的环境中,仍然可能成为问题。

  4. 代码可读性和可维护性: 旧版代码中的“岔道口”注释说明了两种选择(选或不选当前物品)的递归调用,但代码结构并未清晰地反映出这两种选择的逻辑关系。改进后的版本通过条件判断和嵌套结构,使代码逻辑更为直观,增强了可读性和可维护性。

总结而言,旧版本代码的主要缺点在于未利用剪枝策略来避免无用搜索,导致算法效率低下,内存消耗可能较大,并且代码结构不够清晰。这些问题在改进后的版本中得到了有效改善。

改进

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn=30;

int n,V,maxValue;
int w[maxn],c[maxn];

//void dfs(int index,int sumW,int sumC){
//	if(index==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件物品 
//} 

// 改进优化---剪枝
void dfs(int index,int sumW,int sumC){
	if(index==n) return;
	
	dfs(index+1,sumW,sumC);  //不选
	
	if(sumW+w[index]<=V){
		//更新最大价值 
		if(sumC+c[index]>maxValue) maxValue=sumC+c[index];
		
		dfs(index+1,sumW+w[index],sumC+c[index]);  //选 
	} 
} 

int main(){
	scanf("%d%d",&n,&V);
	for(int i=0;i<n;i++) scanf("%d",&w[i]);
	for(int i=0;i<n;i++) scanf("%d",&c[i]);
	
	dfs(0,0,0);
	
	printf("%d",maxValue);
	 
	return 0; 
} 

新版本代码对原始的深度优先搜索(DFS)算法进行了优化,引入了剪枝策略。这种改进的好处体现在以下几个方面:

  1. 减少无用搜索: 原始版本的DFS在递归过程中,即使后续选择可能导致总重量超过背包容量,也会尝试选择当前物品。而在改进版本中,添加了条件判断 if(sumW+w[index]<=V),只有当选择当前物品后总重量仍不超过背包容量时,才继续进行递归搜索。这样,对于那些会导致总重量超限的选择,程序会提前终止这部分递归路径,避免了不必要的计算,大大减少了无用搜索空间。

  2. 提高效率: 通过剪枝,程序减少了无效递归调用次数,从而降低了时间复杂度。对于背包问题这类NP完全问题,尽管深度优先搜索无法保证在最坏情况下达到最优解的时间复杂度,但合理的剪枝策略可以显著提升实际运行效率,尤其是在问题规模较大或数据分布有利于剪枝时。

  3. 简化逻辑: 改进后的代码结构更为简洁,将“不选”和“选”两种情况合并到了同一个递归函数中。在满足重量约束的前提下,先更新最大价值(若有),然后才进行“选”的递归调用。这样的处理方式使得代码逻辑更加紧凑,易于理解与维护。

总结来说,改进后的写法通过剪枝策略有效地减少了无用搜索,提高了算法效率,同时简化了代码结构。这对于处理背包问题等需要大量搜索的场景具有明显优势。

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

captain_dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值