深度优先搜索(DFS)

本文介绍了深度优先搜索(DFS)的概念及其在解决0/1背包问题中的应用。通过递归实现DFS,针对每件物品选择放入或不放入背包,寻找最大价值组合。在原有代码基础上进行了剪枝优化,只有当物品加入后总重量不超过背包容量时,才会继续深入搜索,从而减少计算量。最终,该方法能有效求解在不超过背包容量的情况下,物品的最大价值组合。
摘要由CSDN通过智能技术生成

深度优先搜索

深度优先搜索:从起点开始,当碰到岔道口时,总是选择其中一条岔路前进,在岔路上如果又遇到新的岔道口,仍然选择新岔道口的其中一条岔路前进,直到碰到死胡同才回退到最近的岔道口选择另一条岔路。(不碰到死胡同就不回头)

深度优先搜索是一种枚举所有完整路径以遍历所有清空的搜索方法。

使用递归可以很好地实现深度优先搜索,系统会调用一个叫系统栈的东西来存放递归中每一层的状态,因此使用递归来实现DFS的本质还是栈。

例题

有n件物品,每件物品的重量为w[i],价值为c[i]。现在需要选出若干物件放入一个容量为V的背包中,使得在选入背包的物品重量和不超过容量V的前提下,让背包中物品的价值之和最大,求最大值(1<=n<=20)

分析

对每件物品都有选或者不选两种选择,而这就是所谓的“岔道口”。题目要求选择的物品重量总和不能超过V,一旦超过就会到达“死胡同”,需要返回最近的“岔道口”。
DFS函数的参数中必须记录当前处理的物品编号index,已选物品的总重量sumV与总价值sumC。

void DFS(int index, int sumW, int sumC){...}

如果选择不放入index号物品,那么sumW与sumC就将不变
接下来处理index+1号物品,即前往DFS(index+1, sumW, sumC)这条分支
如果选择放入index号物品,那么sumW将增加当前物品的重量w[index],sumC将增加当前物品的价值c[index]
接着处理index+1号物品,即前往DFS(index+1, sumW+w[index], sumC+c[index])这条分支

一旦index增长到n,则说明已经把n件物品处理完毕,此时记录的sumW和sumC就是所选物品的总重量和总价值。
如果sumV不超过V且sumC大于一个全局的记录最大总价值的变量maxValue,就说明当前方案可以得到更大价值,用sumC更新maxValue。

#include <cstdio>
const int maxn = 30;
int n, V, maxValue = 0; //物品件数n,背包容量V,最大价值maxValue
int w[maxn], c[maxn]; //w[i]为每件物品的重量,c[i]为每件物品的价值
//DFS,index为当前处理的物品编号
//sumW,sumC分别为当前总重量和当前总价值
void DFS(int index, int sumW, int sumC)
{
	if(index == n) //已经完成对n件物品的选择(死胡同)
	{
		if(sumW <= V && sumC > maxValue)
		{
			maxValue = sumC; //不超过背包容量时更新最大价值maxValue
		}
		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); //初始时为第0件物品,当前总重量和总价值均为0
	printf("%d\n", maxValue);
	return 0;
}
//输入
5 8 //5件物品,背包容量8
3 5 1 2 2 //重量分别为3 5 1 2 2
4 5 2 1 3 //价值
10 //输出结果

上述代码,总是把n件物品的选择全部确定之后才去更新最大价值,但事实上忽视了背包容量不超过V这个特点。
可以只有当sumW<=V时才进入岔道。可以降低计算量(剪枝)

void DFS(int index, int sumW, int sumC)
{
	if(index == n)
	{
		return; //已经完成对n件物品的选择
	}
	DFS(index + 1, sumW, sumC); //不选第index件物品
	//只有加入第index件物品后未超过容量V,才能继续
	if(sumW + w[index] <= V)
	{
		if(sumC + c[index] > ans)
		{
			ans = sumC + c[index]; //更新最大价值maxValue
		}
		DFS(index + 1, sumW + w[index], sumC + c[index]); //选第index件物品
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值