回溯算法非常适合用递归来实现,在实现的过程中,剪枝操作是提高回溯效率的一种技巧。利用剪枝,我们并不需要穷举搜索所有的情况,从而提高搜索效率。
回溯算法的核心思想就是:
1:递归之前「做选择」;
2:递归之后「撤销选择」。
以下实例为0-1背包问题,背包承重极限是一定的,每个物体的价值都不一样,
1、MaxWeight 函数不计算物体价值,挑选出背包承重极限以内最大承重的组合;
2、WeightValue 函数则在满足背包承重极限的前提下,挑选出总价值最高的组合。
#include <iostream>
#include <vector>
void MaxWeightFunc(int* weight, int nLength, int nWeightLimit, int i, int nCurrentWeight, \
int& nMaxWeight, std::vector<bool>& vec, std::vector<std::vector<bool>>& vecvec)
{
if (nCurrentWeight > nWeightLimit) {
return;
}
if (i >= nLength) {
if (nCurrentWeight > nMaxWeight) {
nMaxWeight = nCurrentWeight;
vecvec.clear();
vecvec.push_back(vec);
} else if (nCurrentWeight == nMaxWeight) {
vecvec.push_back(vec);
}
return;
}
vec.push_back(false);
MaxWeightFunc(weight, nLength, nWeightLimit, i + 1, \
nCurrentWeight, nMaxWeight, vec, vecvec);
vec.back() = true;
MaxWeightFunc(weight, nLength, nWeightLimit, i + 1, \
nCurrentWeight + weight[i], nMaxWeight, vec, vecvec);
vec.pop_back();
}
void MaxWeight(int* weight, int nLength, int nWeightLimit)
{
std::cout << std::endl << "Source weight: " << std::endl;
for (int i = 0; i < nLength; i++) {
std::cout << weight[i] << ' ';
}
std::cout << std::endl;
std::vector<bool> vec;
std::vector<std::vector<bool>> vecvec;
int nMaxWeight = 0;
MaxWeightFunc(weight, nLength, nWeightLimit, 0, 0, nMaxWeight, vec, vecvec);
std::cout << "Max weight: " << nMaxWeight << std::endl;
for (auto it = vecvec.begin(); it != vecvec.end(); it++) {
for (auto iter = it->begin(); iter != it->end(); iter++) {
std::cout << *iter << ' ';
}
std::cout << std::endl;
}
std::cout << std::endl;
}
void WeightValueFunc(int* weight, int* value, int nLength, int nWeightLimit, int i, int nCurrentWeight, \
int nCurrentValue, int& nMaxValue, std::vector<bool>& vec, std::vector<std::vector<bool>>& vecvec)
{
if (nCurrentWeight > nWeightLimit) {
return;
}
if (i >= nLength) {
if (nCurrentValue > nMaxValue) {
nMaxValue = nCurrentValue;
vecvec.clear();
vecvec.push_back(vec);
} else if (nCurrentValue == nMaxValue) {
vecvec.push_back(vec);
}
return;
}
vec.push_back(false);
WeightValueFunc(weight, value, nLength, nWeightLimit, i + 1, \
nCurrentWeight, nCurrentValue, nMaxValue, vec, vecvec);
vec.back() = true;
WeightValueFunc(weight, value, nLength, nWeightLimit, i + 1, \
nCurrentWeight + weight[i], nCurrentValue + value[i], nMaxValue, vec, vecvec);
vec.pop_back();
}
void WeightValue(int* weight, int* value, int nLength, int nWeightLimit)
{
std::cout << std::endl << "Source weight: " << std::endl;
for (int i = 0; i < nLength; i++) {
std::cout << weight[i] << ' ';
}
std::cout << std::endl;
std::cout << "Source value: " << std::endl;
for (int i = 0; i < nLength; i++) {
std::cout << value[i] << ' ';
}
std::cout << std::endl;
std::vector<bool> vec;
std::vector<std::vector<bool>> vecvec;
int nMaxValue = 0;
WeightValueFunc(weight, value, nLength, nWeightLimit, 0, 0, 0, nMaxValue, vec, vecvec);
std::cout << "Max value: " << nMaxValue << std::endl;
for (auto it = vecvec.begin(); it != vecvec.end(); it++) {
for (auto iter = it->begin(); iter != it->end(); iter++) {
std::cout << *iter << ' ';
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main()
{
int weight[] = { 21, 58, 13, 36, 5, 18, 42, 1, 10, 8 };
int value[] = { 4, 7, 3, 9, 1, 14, 8, 10, 5, 20 };
MaxWeight(weight, sizeof(weight) / sizeof(weight[0]), 100);
WeightValue(weight, value, sizeof(weight) / sizeof(weight[0]), 100);
return 0;
}