0-1背包问题的回溯法实现

0-1背包问题的回溯法实现,不知道为啥要做一个回溯法实现。
2^n状态的搜索树,枚举

#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<algorithm>
#define Maxn 10000

using namespace std;
int mn[Maxn],mnn[Maxn],perw[Maxn],maxw;

template<class Typew, class Typep>
class Knap {
public:
    Typep Bound(int i);
    void Backtrack(int i);
    Typew c;//容量
    int n;
    Typew *w;//重量
    Typep *p;//价值
    Typew cw;//当前重量
    Typep cp;//当前价值
    Typep bestp;//当前最优价值,,保存答案
};

template<class Typew, class Typep>
void Knap<Typew, Typep>::Backtrack(int i) {
    if (i > n) {//搜索树 叶节点
        bestp = cp;
        maxw = cw;
        memcpy(mnn, mn, (n + 1) * sizeof(int));
        return;
    }
    if (cw + w[i] <= c) {//进入左子树
        mn[i] = 1;
        cw += w[i];
        cp += p[i];
        Backtrack(i + 1);
        mn[i] = 0;
        cw -= w[i];
        cp -= p[i];// 回溯
    }
    if (Bound(i + 1) > bestp) {//进入右子树
        mn[i] = 0;
        Backtrack(i + 1);
    }

}

template<class Typew, class Typep>
Typep Knap<Typew, Typep>::Bound(int i) {//计算上界
    Typew cleft = c - cw;//剩余容量
    Typep b = cp;
    while (i <= n && w[i] <= cleft) {//以物品单位重量价值递减序装入背包
        cleft -= w[i];
        b += p[i];
        i++;
    }
    if (i < n) //装满背包
        b += p[i] * cleft / w[i];
    return b;
}

class Object {
public:
    int operator<=(Object a) const { return (d >= a.d); }
public:
    int ID;
    double d;
};
bool tmp(Object a, Object b) { return a.operator<=(b); }
void Sort(Object *pObject, int n);
template<class Typew, class Typep>
Typep Knapsack(Typep p[], Typew w[], Typew c, int n) {//初始化
    Typew W = 0;
    Typep P = 0;
    Object *Q = new Object[n];
    for (int i = 1; i <= n; i++) {
        Q[i - 1].ID = i;
        Q[i - 1].d = 1.0 * p[i] / w[i];
        P += p[i];
        W += w[i];
    }
    if (W < c)//装入所有物品
        return P;
    Sort(Q, n);//依物品单位重量价值排序

    cout << endl;
    Knap<Typew, Typep> K;
    K.p = new Typep[n + 1];
    K.w = new Typew[n + 1];
    for (int i = 1; i <= n; i++) {
        K.p[i] = p[Q[i - 1].ID];
        K.w[i] = w[Q[i - 1].ID];
    }
    K.cp = 0;
    K.cw = 0;
    K.c = c;
    K.n = n;
    K.bestp = 0;
    K.Backtrack(1);//回溯搜索
    cout << "按单位重量价值排序:";
    for (int i = 1; i <= n; i++) {

        cout << Q[i - 1].ID << " ";
        perw[Q[i - 1].ID] = mnn[i];
    }
    cout<<endl;
    delete[] Q;
    delete[] K.w;
    delete[] K.p;
    return K.bestp;

}

void Sort(Object *pObject, int n) {
    sort(pObject, pObject + n, tmp);
}
int main() {
    int c, n;
    cout << "请输入物品数量n:";
    cin >> n;
    cout << "请输入背包容量c:";
    cin >> c;
    int *w = new int[n];
    cout << "请依次输入物品重量w:" << endl;
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
    }
    int *p = new int[n];
    cout << "请依次输入物品价值p:" << endl;
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
    }
    int bestp = Knapsack(p, w, c, n);
    cout << "各物品装载情况:";
    for (int i = 1; i <= n; i++) {
        cout <<i<<"号物品 ";
    }
    cout << endl;
    cout << "各物品装载情况:";
    for (int i = 1; i <= n; i++) {
        cout<<setw(6)<<left << perw[i]<<" ";
    }
    cout << endl;
    cout << "能够装载的最大价值为:";
    cout << bestp << endl;
    cout << "能够装载的最大重量为:";
    cout << maxw << endl;
    return 0;
}
/*
7
150
35
30
60
50
40
10
25
10
40
30
50
35
40
30
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值