算法分析与设计实验报告——0-1背包问题的回溯算法实现

算法分析与设计实验报告——0-1背包问题的回溯算法实现

目录:

  • 算法分析与设计实验报告——0-1背包问题的回溯算法实现
    • 一、 实验目的
    • 二、实验要求
    • 三、 实验原理
    • 四、 实验过程(步骤)
    • 五、 运行结果
    • 六、实验分析与讨论
    • 七、实验特色与心得
    • 附件一 实验过程(步骤)
      • 递归法
      • 非递归法
    • 附件二 运行结果
      • 递归法
      • 非递归法

一、 实验目的

掌握回溯法的基本思想和解决问题的基本步骤,认识回溯法和动态规划、贪心选择的联系与区别,对比解决同一问题的三种算法设计策略的优缺点。

二、实验要求

用c++语言实现递归回溯回溯和迭代回溯解决0-1背包问题,分析时间复杂性,体会回溯法解决问题的基本思路和步骤。

三、 实验原理

四、 实验过程(步骤)

见附件一
实验步骤、特点
重要源代码(流操作的部分要醒目的提示并注释)

五、 运行结果

见附件二

六、实验分析与讨论

遇到的问题,及解决方案

七、实验特色与心得

附件一 实验过程(步骤)

递归法

/*
 * Algorithm experiment 7 0-1背包问题的回溯算法递归实现
 */
#include "bits/stdc++.h"

#define maxn 10000
using namespace std;
int mn[maxn] = {0};
int mnn[maxn] = {0};
int perw[maxn] = {0};
int maxw = 0;

template<class Typew, class Typep>
class Knap {
public:
    // friend Typep Knapsack(Typep *, Typew *, Typew, int);

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:
    // friend int Knapsack(int *, int *, int, int);

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++) {
        printf("w[%d]:", i);
        cin >> w[i];
    }
    int *p = new int[n];
    cout << "请依次输入物品价值p:" << endl;
    for (int i = 1; i <= n; i++) {
        printf("p[%d]:", 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
 */


非递归法

/*
 * Algorithm experiment 7 0-1背包问题的回溯算法非递归实现
 */
#include "bits/stdc++.h"

#define maxn 10000
using namespace std;
int mn[maxn] = {0};
int mnn[maxn] = {0};
int perw[maxn] = {0};
int cnt[maxn] = {0};
int maxw = 0;

template<class Typew, class Typep>
class Knap {
public:
    // friend Typep Knapsack(Typep *, Typew *, Typew, int);

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) {
    while (i >= 1) {
        if (cnt[i] <= 1) {
            for (int j = cnt[i]; j <= 1; j++) {
                if (i > n) {
                    bestp = cp;
                    maxw = cw;
                    memcpy(mnn, mn, (n + 1) * sizeof(int));
                    i--;
                }
                int child = 1 - cnt[i];
                if (child) {
                    if (cw + w[i] <= c) {//进入左子树
                        mn[i] = 1;
                        cw += w[i];
                        cp += p[i];
                        cnt[i]++;
                        i++;
                    } else
                        cnt[i]++;
                } else {
                    if (Bound(i + 1) > bestp) {//进入右子树

                        mn[i] = 0;
                        cnt[i]++;
                        i++;
                    } else
                        cnt[i]++;
                }
            }
        } else {
            cnt[i] = 0;
            i--;
        }
    }
}


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:
    // friend int Knapsack(int *, int *, int, int);

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++) {
        printf("w[%d]:", i);
        cin >> w[i];
    }
    int *p = new int[n];
    cout << "请依次输入物品价值p:" << endl;
    for (int i = 1; i <= n; i++) {
        printf("p[%d]:", 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-1背包问题的回溯算法实现_第1张图片

非递归法

算法分析与设计实验报告——0-1背包问题的回溯算法实现_第2张图片

你可能感兴趣的:(算法实验笔记,算法,c++)