0-1背包问题

来源:互联网 发布:手机模拟期货软件 编辑:程序博客网 时间:2024/06/07 13:15

回溯法:

#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>[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);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;}


原创粉丝点击