C++使用DFS算法实现acwing背包问题

介绍

        用dfs函数解决背包问题是可以解决的,但是每一次都要把所有的结果都遍历一遍,当物品的

        数量达到20左右时,计算机就会变得十分吃力,实际上用dp算法会解决的更快,用dfs解决背

        包问题纯属只是用来学习的而已,请各位以学习的心态观看,欢迎各位大佬指点。

实现DFS算法

        dfs算法表示在a[n]的所有数字当中,通过所有组合方式,是否能找出等于k的组合。

        例:n=3k=5a[n]={3,1,2};

        a[0]+a[2]=k=5;返回true;

        dfs算法可以把a[3]中所有数字组合都遍历,找出是否有组合等于k,遍历的方式如图下:

        

         可以看出,dfs算法把所有a[0]、a[1]、a[2]组合的所有可能性都列了出来,当遍历到dfs(3,a[0]+a[1])时,满足判断条件,退出dfs算法

        了解了dfs算法的原理,编程实现代码如下:

bool dfs(int i, int sum,int worth)
{
	if (i == n)return sum == k;
	if (dfs(i + 1, sum, worth))return true;
	if (dfs(i + 1, sum + a[i], worth + b[i]))return true;
	return false;
}

 背包问题

        有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

        第  i 件物品的体积是 vi ,价值是 wi

        求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
        输出最大价值。

对比DFS算法

        在dfs算法当中,当遍历到某个组合,满足数组中的某组合=k时,就会结束遍历

        背包问题当中,需要找出未超过背包体积的所有组合中,求出价值最大的组合是哪一个

修改代码

        在dfs代码中,只要遍历到某组合满足=k时,接下来的组合将不再遍历;

        而判断是否满足条件的语句是第一行:if (i == n)return sum == k;

        当i==n时,return的值的判断条件,  当sum==k时, 就会结束遍历,并返回true ,表示可以          找到组合等于k

        如果把sum == k;换成false,表示无论如何都会遍历所有可能性

        修改后的代码如下:

int dfs(int i, int sum)
{
	if (i == n)return false;
	if (dfs(i + 1, sum, worth))return true;
	if (dfs(i + 1, sum + a[i]))return true;
	return false;
}

        背包问题中设计到的不止体积k,还涉及到了价值,所以需要增加传入参数:worth

int dfs(int i, int sum,int worth)
{
	if (i == n)return false;
	if (dfs(i + 1, sum, worth))return true;
	if (dfs(i + 1, sum + a[i], worth + b[i]))return true;
	return false;
}

       ......

        接下来需要解决,(容量sum未超过总体积时),组合条件满足题意而且(当价值worth的值

        大于上一次 worth 的值时),需要覆盖上一次worth的值。

        

if (sum <= k && worth > f)
	{
		f = worth;
		worth = 0;
	}

        ......

        无论递归函数递归了第几次,始终再第一次进入函数时的状态时dfs[0,0,0]跳出函数。

        即函数的三个值都为0时,表示递归进入了最后阶段,这时候不需要返回false,返回f价值。

if (i == 0 && sum == 0 && worth == 0)return f;

        再把函数类型bool型,改成int;

最终代码如下:

#include<iostream>
using namespace std;

const int MAX = 1000;
int a[MAX],b[MAX];
int n, k, f = 0;

int dfs(int i, int sum,int worth)
{
	if (sum <= k && worth > f)
	{
		f = worth;
		worth = 0;
	}
	if (i == n)return false;
	if (dfs(i + 1, sum, worth))return true;
	if (dfs(i + 1, sum + a[i], worth + b[i]))return true;
	if (i == 0 && worth == 0)return f;
	return false;
}

int main()
{
	cin >> n >> k;
	for (int i = 0; i < n; i++)cin >> a[i] >> b[i];

	cout << dfs(0, 0, 0) << endl;
	return 0;
}

感谢各位收看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值