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
*/