您的位置:首页 > 其它

0-1背包问题

2017-12-01 22:36 148 查看
回溯法:

#include <iostream>
#include <iomanip>
using namespace std;

int k = 0;//index 的序号
int h = 0;//向上回溯了h个节点

template <class Typew, class Typep>
class Knap
{
friend Typep Knapsack(Typep*, Typew*, Typew, int);
//private:
public:
Typep Bound(int i);
void Backtrack(int i);
Typew c; //背包容量
int n; //物品数
Typew *w;//物品重量数组
Typep *p;//物品价值数组
Typew cw;//当前重量
Typep cp;//当前价值
Typep bestp;//当前最优价值
int *index;//满足条件的组合中物品号
};
//回溯函数
template <class Typew, class Typep>
void Knap<Typew, Typep>::Backtrack(int i) //i是当前节点
{

if (i > n) //到达叶子节点
{
bestp = cp;
return;
}
if (cw + w[i] <= c) //进入左子树
{
cw += w[i];
cp += p[i];
k++;
index[k] = i;
Backtrack(i + 1);

cw -= w[i];
cp -= p[i];
h++;//向上回溯了h个节点
}
if (Bound(i + 1)> bestp) //进入右子树
{
if(h>0) k -= h;
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;
}

template <class Typew, class Typep>
class Object
{
friend Typep Knapsack(Typep *, Typew *, Typew, int);
public:
int operator <=(Object a)const
{
return (d >= a.d);
}
Object& operator =(Object a)
{
d = a.d;
ID = a.ID;
return *this;
}
//private:
int ID;
float d; //单位价值
};

//排序函数
template <class Typew, class Typep>
void Sort(Object<Typew, Typep> Q[], int n)
{
Object<Typew, Typep> tempt;
int flag;
for (int i = 0; i < n; i++)
{
flag = i;
for (int j = i + 1; j < n; j++)
{
if (Q[j].d > Q[flag].d) flag = j;
}
if (flag != i)
{
tempt = Q[i];
Q[i] = Q[flag];
Q[flag] = tempt;
}
//cout << Q[i].ID << ":" << Q[i].d << endl;
}
}

template <class Typew, class Typep>
Typep Knapsack(Typep p[], Typew w[], Typew c, int n)
{//Backtrack的初始化
Typew W = 0;
Typep P = 0;
Object<Typew, Typep> *Q = new Object<Typew, Typep>
;
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);
Knap<Typew, Typep> K;
K.p = new Typep[n + 1];
K.w = new Typew[n + 1];
K.index = new int[n + 1];
for (int i = 1; i <= n; i++)
{
K.p[i] = p[Q[i - 1].ID]; //cout<<i<<":"<<K.p[i]<<" ";
K.w[i] = w[Q[i - 1].ID]; //cout<<i<<":"<<K.w[i]<<endl;
K.index[i] = 0;
}
K.cp = 0;
K.cw = 0;
K.c = c;
K.n = n;
K.bestp = 0;

//回溯搜索
K.Backtrack(1);

cout <<"可放入的物品列表:\n\n"<< "单位价值排名 " << "重量 " << "价值" << endl;
for (int i = 1; i <= n; i++)
{
if (K.index[i] != 0)
cout <<setw(8)<< K.index[i] << " " << K.w[K.index[i]] << " " << K.p[K.index[i]] << endl;
}
delete[] Q;
delete[] K.w;
delete[] K.p;
//delete[] K.index; //不知道为什么,有这个delete程序就没办法返回

return K.bestp;
}

int main()
{
int c = 92;
int n = 7;
int p[8] = { 0, 55, 45, 65, 30, 40, 35, 30 };
int w[8] = { 0, 15, 16, 15, 13, 20, 18, 14 };

Knap<int, int> K;
cout << "\n最多可装价值为: "<<Knapsack<int, int>(p, w, c, n)<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: