实验 3
学院:数据科学与计算机学院
【实验内容】
背包问题: 假设有一个能装入总体积为 T 的背包和 n 件体积分别为 W1,W2,…, Wn 的物品, 能 否 从 n 件物品中挑选若干件恰好装满背包,即使 Wi1+Wi2+…Wim=T,要求找出所有满足上述条件的解。例如,当 T=10,各件物 品的体积为{1,8,4,3,5,2}时,可找到 4 组解: (1,4,3,2), (1,4,5), (8,2), (3,5,2)。
【数据结构与算法】
堆栈、递归思想、利用堆栈将递归转换成非递归的解决方法
【实验步骤】 1.先处理好数据读入 2.用 left 标记背包剩余容量,用 i 标记当前处理到的物品,用栈 s 存储需 要放进书包里的物品。 3.在循环里处理数据,当判断到处理完毕,用 break 退出循环。 4.(3)中循环中,先判断 i 物品能否放入背包,能则压进栈 s 里,然后判断 剩余容量 left 是否为 0,若为 0,输出结果,并且使栈 s 和 i 为下一情况,若不 为 0,则通过进一步判断决定 i 的值和栈 s 的状态。
【实验结果】
1.题目例子
2、另外举例
3、无解的输入(背包体积过大)
4、无解的输入(物品质量太大)
代码
#include<iostream>
#include<cstdlib>
#include <stack>
#define max 1000
using namespace std;
int main() {
// read the datas
int T, n;
int W[max];
bool found = false;
cout << "please enter the capacity of the backpack : ";
cin >> T;
cout <<endl << "please enter the number of things(less than 1000) : ";
cin >> n;
cout <<endl << "please enter the weight of each things : " <<endl;
for (int j = 0; j < n; j++) cin >> W[j];
cout << endl << "the answer is: " << endl;
// process
int left = T;
stack<int> s;
int i = 0;
while (1) {
if (left == W[i] || (left > W[i] && i < n)) { // 可以放进背包的情况
s.push(i);
left -= W[i];
}
if (left == 0) { // 刚好装满
// 标记
found = true;
// 输出结果
stack<int> t;
while (!s.empty()) {
t.push( s.top());
s.pop();
}
cout << "( ";
while (!t.empty()) {
cout << W[t.top()] << " ";
s.push(t.top());
t.pop();
}
cout << ")" <<endl;
// 处理下一情况
if (s.size() == 1) {
left += W[s.top()];
s.pop();
i++;
if (i == n) break;
} else if (i == n-1) {
left += W[s.top()];
s.pop();
i = s.top() + 1;
left += W[s.top()];
s.pop();
} else {
i = s.top() + 1;
left += W[s.top()];
s.pop();
}
} else { // 不能装满
if (i == n-1) { // i遍历到最后一个物品
if (s.size() == 1 && s.top() == n - 1) {
break;
} else {
if (i == s.top()) {
left += W[s.top()];
s.pop();
i = s.top() + 1;
left += W[s.top()];
s.pop();
} else {
i = s.top() + 1;
left += W[s.top()];
s.pop();
}
}
} else { // 其他情况
i++;
}
}
}
if (found == false) cout << "No answer." << endl;
system("pause");
return 0;
}