数据结构-背包问题

实验 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;
}
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值