简化的背包问题

文章目录

参考

概述

有n个物品重量分别为(),能否从这n个物品中挑选若干物品使重量为T。若有解给出全部解

思路

因为要是有解则给出全部解。
dfs,回溯法。解空间:每个东西取或者不取两种情况。剪枝函数:当>=的时候返回。
怎么描述这个解呢?比如说有一个背包,里面有物品重量为,{2,3,5,4},那么对第i个物品有取(1)或者不取(0)两种情况。解空间如下
在这里插入图片描述
这里只画到了第三层。
可以看到,到了每一层,要做的事情都是相同的。拿画圆圈的那一个为例子,假设之前的数组中已经存了01,那么接下来要做的事情是:1.判断(相当于一个剪枝函数)。看看当前物品总重量。当前背包总重量为3,要是超过了要求的总重量,那么此路不通,return;要是等于要求的总重量,那么得到结果,输出当前的结果,return;要是小于要求的总重量,那么还需要继续确定下一个物品取或者不取。2.确定取,或者不取两种情况。并确定数组的下一个数字为1或者0.那么新数组为010,011.把这两个数组传入递归函数,再次进行同样的操作。

code

#include<stdio.h>
#include<iostream>
#define SIZE 8
using namespace std;
int num = 1; 
void get(int bag[], int result[], int T, int i);//确定当前第i个位置 
void print(int result[]);//打印结果 
int main()
{
	int bag[SIZE] = {2, 4, 1, 3, 1, 5, 2, 8};
	int result[SIZE] = {0};
	int T = 10;
	get(bag, result, T, 0);
	return 0;
}
void get(int bag[], int result[], int T, int i)
{
	//返回条件 
	if(T == 0)
	{
		print(result);//输出结果 
	}
	//如果如果超出去了,或者全选完了,返回 
	else if(T < 0 || i == SIZE)
	{
		return;
	}
	else
	{
		//不取 
		result[i] = 0;
		get(bag, result, T, i + 1);
		//取 
		result[i] = 1;
		get(bag, result, T - bag[i], i + 1);
	}
}
void print(int result[])
{
	int i;
	cout<<"第"<<num<<"组:";
	for(i = 0; i < SIZE; i++){
		if(result[i] == 1)
		{
			cout<<i<<" ";
		}
	} 
	cout<<endl;
	num++;
}

不知道为什么会出现奇奇怪怪的结果,貌似进行下一种的时候result数组中还存着前面的结果。
在这里插入图片描述
试着在每次达到目标之后把result后面还没有遍历的值都赋0,就解决了这个问题。但是result是什么时候改变的呢?

while(i < SIZE){
			result[i] = 0;
			i++;
		}

加上了上面这段代码后结果对比
在这里插入图片描述
可以看出来应该答案是找对了的,但是result后面还没遍历的项为啥是1呢?
问题出在,在调用了get(bag, result, T, i + 1);之后,result数组i+1后面的值已经改变了,我还以为没改。所以这个时候要把result后面的值重新赋0.
所以在两个get()函数之间加入这段代码即可

int k = i;
		while(k < SIZE){
			result[k] = 0;
			k++;
		}
发布了74 篇原创文章 · 获赞 4 · 访问量 1436

猜你喜欢

转载自blog.csdn.net/weixin_44814121/article/details/101520476
今日推荐