背包问题之一(回溯法)

背包问题分为很多种,其核心不过是寻找全部解或最优解的问题。

这篇文章就其中一个典型问题进行讲解。

题目:一个容积为T的背包,和n件体积不等的物品,选出若干件物品刚好装满背包,列出所有的组合。

显然回溯法可以解决这个问题。回溯法是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,迷宫问题是这种方法最直观典型的应用。

首先要借助一个数组存储全部物品,一个vector存储一组满足条件物品,再写一个递归调用的函数selectgood(int rest, int position), rest是背包剩余的容积,position代表当前搜索的位置。当搜索到currentposition时,假设此时背包剩余容积为currentrest,那么有两种情况,一种是选择不将当前物品放入背包,则调用函数selectgood(currentrest, currentposition+1),另一种情况是将当前物品放入背包,但是在这种情况里如果当前物品的体积大于currentrest,则不能继续,如果不大于,则将当前物品放入vector,再判断当前的rest,若背包恰好装满,则输出当前vector里面的一组,若还未装满,则调用selectgood(currentrest,currentposition+1),最后当装有当前物品的所有满足情况输出后,在函数最后将当前物品从vector取出。

代码:

#include<iostream>
#include<vector>
using namespace std;
int count = 0;
vector<int> mine;
int all[100];
int T, n;
void selectgood(int rest, int position) {
	if (rest == 0) return;
	if (position == n) return;
	selectgood(rest, position+1);
	if (rest < all[position]) return;
	mine.push_back(all[position]);
	if (rest == all[position]) {
		count++;
		vector<int>::iterator iter;
		for (iter = mine.begin(); iter != mine.end(); iter++) {
			cout << *iter << " ";
		}
		cout << endl;
	}
	selectgood(rest-all[position], position+1);
	mine.pop_back();
}
int main() {
	cin >> T >> n;
	for (int i = 0; i < n; i++) {
		cin >> all[i];
	}
	selectgood(T, 0);
	cout << "Totally " << count << " sets of solutions" << endl; 
}
    原文作者:回溯法
    原文地址: https://blog.csdn.net/monkey_rose/article/details/52765751
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞