简单的背包填满问题:(题目参考这个网站)
假设有一个能装入容量为C的背包和n件重量分别为w1,w2,…,wn的物品,能否从n件物品中挑选若干件恰好装满背包,要求找出所有满足上述条件的解。
示例答案:当C=10,各件物品重量为{1,8,4,3,5,2}时,可以找到下列4组解:(1,4,3,2)、(1,4,5)、(8,2)和(3,5,2)。
上述网站给出了一种解法,我这里给出另一种解法。我的解题思路:
每个物品只有两种可能,拿或不拿,n个物品共有2的n次方种可能,遍历所有可能就可以求出所有满足条件的解。
问题转换为:一个n维数组,数组的每个元素为1或0,如何快速遍历这个数组的所有取值情况。
核心递归算法:
//递归实现n维0/1数组的取值情况遍历
//使用时vec初始化为全零数组,i初始化为0,递归前先进行一次operation
//递归时vec的第i个元素进行变化
void TraverseVector(vector vec, int i)
{
//如果i超出vec范围,则返回
if (i == vec.size())
return;
//递归
TraverseVector(vec, i + 1);
//变化第i个元素,进行操作
vec[i] = 1;
//operation
/*以输出为例
for (int o = 0; o < vec.size(); o++)
cout << vec[o] << ' ';
cout << endl;*/
//递归
TraverseVector(vec, i + 1);
}
更改上述算法中的operation部分即可解决我们的背包填满问题,完整代码如下:
//假设有一个能装入容量为C的背包和n件重量分别为w1,w2,,...,wn的物品,能否从n件物品中挑选若干件恰好装满背包,要求找出所有满足上述条件的解。
//当C=10,各件物品重量为{1,8,4,3,5,2}时,可以找到下列4组解:(1,4,3,2)、(1,4,5)、(8,2)和(3,5,2)。
//每个物品只有两种可能,拿或不拿,n个物品共有2的n次方种可能,遍历所有可能就可以求出所有满足条件的解
//问题转换为:一个n维数组,数组的每个元素为1或0,如何快速遍历这个数组的所有取值情况
#include "pch.h"
#include
#include
using namespace std;
//递归实现n维0/1数组的取值情况遍历
//使用时vec初始化为全零数组,i初始化为0,递归前先进行一次operation
//递归时vec的第i个元素进行变化
void TraverseVector(vector vec, int i)
{
//如果i超出vec范围,则返回
if (i == vec.size())
return;
//递归
TraverseVector(vec, i + 1);
//变化第i个元素,进行操作
vec[i] = 1;
//operation
/*以输出为例
for (int o = 0; o < vec.size(); o++)
cout << vec[o] << ' ';
cout << endl;*/
//递归
TraverseVector(vec, i + 1);
}
//给出拿取情况向量与重量列表向量,求解当前背包重量
int CalculateWeight(vector taken_items, vector weights)
{
int weight = 0;
for (int i = 0; i < taken_items.size(); i++)
weight = weight + taken_items[i] * weights[i];
return weight;
}
//根据拿取情况向量输出结果
void PrintResult(vector taken_items, vector weights)
{
cout << "【求解结果】该组合满足条件";
for (int i = 0; i < taken_items.size(); i++)
if (taken_items[i])cout << weights[i] << ' ';
cout << endl;
}
void BackpackProblem(vector vec, int i, int capacity, vector weights)
{
//如果i超出vec范围,则返回
if (i == vec.size())
return;
//递归
BackpackProblem(vec, i + 1, capacity, weights);
//变化第i个元素,进行操作
vec[i] = 1;
//operation
//判断背包是否已满
if (capacity == CalculateWeight(vec, weights))
PrintResult(vec, weights);
//递归
BackpackProblem(vec, i + 1, capacity, weights);
}
int main()
{
//初始化
int capacity;
vector weights;
int number;
cout << "输入背包容量及物品件数:" << endl;
cin >> capacity >> number;
cout << "输入这" << number << "个物品的重量" << endl;
for (int i = 0; i < number; i++)
{
int weight;
cin >> weight;
weights.push_back(weight);
}
//定义拿取情况向量
vector taken_items(number, 0);
//定义遍历元素i
int i = 0;
//由于一个都不拿肯定不满足装满背包的条件,故无需操作当前向量,直接开始递归
BackpackProblem(taken_items, i, capacity, weights);
return 0;
}
/*
输入:
10 6
1 8 4 3 5 2
*/