java分支限界法解决背包问题_分支限界法之0 1背包问题

本文介绍了使用Java实现分支限界法来解决0/1背包问题。通过定义TreeNode结构体,实现LQueue类进行节点的管理,包括添加、移除最大价值节点等操作。通过对物品按单位重量价值进行排序,结合分支限界法的上界计算,寻找最优解。最终在给定的背包容量下,找到能装入的最大价值物品组合。
摘要由CSDN通过智能技术生成

#include "iostream.h"

//tree node

typedef struct _treenode{

//struct _treenode *liveNode; //活节点

double upperProfit; //节点的价值上界

double profit; //节点价值*

double weight; //节点重量

int level; //活节点在子树中所处的层序号

//bool left;

}TreeNode;

void initNode(TreeNode &node, double up, double p, double w, int lev)

{

node.upperProfit = up; node.profit = p; node.weight = w; node.level = lev;

}

///

#define MAX_LENGTH 20

//class LQueue

class LQueue{

public:

LQueue() {length = 0;}

virtual ~LQueue(){}

void addTail(TreeNode tn);

TreeNode removeHead();

TreeNode removeMax();

TreeNode removeMin();

int GetLength(){return length;}

protected:

private:

//int queue[MAX_LENGTH];

TreeNode queue[MAX_LENGTH]; //序号0处开始存储

int length; //节点个数

};

void LQueue::addTail(TreeNode tn)

{

queue[length++] = tn;

}

TreeNode LQueue::removeHead()

{

return queue[--length];

}

TreeNode LQueue::removeMax()

{

double max = 0.0;

int num = -1;

for (int i = 0; i < length; i++)

{

if (max < queue[i].profit)

{

max = queue[i].profit;

num = i;

}

}

TreeNode lq = queue[num];

for (int j = num; j < (length-1); j++) //删除节点

{

queue[j] = queue[j+1];

}

length--;

return lq;

}

TreeNode LQueue::removeMin() //该程序不用

{

return TreeNode();

}

#define ARRAY_LENGTH 4 //物品数

LQueue queue;

double w[] = {3, 5, 2, 1}; double p[] = {9, 10, 7, 4}; int sort[ARRAY_LENGTH];  //{3, 2, 0, 1}

double c; //背包容量7

double cw; //当前重量

double cp; //当前价值

double bestp; //当前最优价值

void init(double cc); //初始化

void sortpw(); //以物品单位重量价值递减序列排序存储于sort[]中

double bound(int i); //计算i层节点价值的上界(i: 0 ~ ARRAY_LENGTH-1)

double bbKnapsack(); //分支限界法求0/1背包问题的解

void main()

{

init(7.0);

sortpw();

double max = bbKnapsack();

cout<

}

void init(double cc)

{

c = cc;

cw = 0.0; cp = 0.0; bestp = 0.0;

}

void sortpw()

{

double pw[ARRAY_LENGTH];

for (int i = 0; i < ARRAY_LENGTH; i++)

{

pw[i] = p[i] / w[i];

}

for (i = 0; i < ARRAY_LENGTH; i++)

{

double max = 0.0;

for (int j = 0; j < ARRAY_LENGTH; j++)

{

if (max < pw[j])

{

max = pw[j];

sort[i] = j;

}

}

pw[sort[i]] = 0.0;

}

}

double bound(int i)

{

double cleft = c - cw;

double b = cp;

while (i < ARRAY_LENGTH && w[sort[i]] <= cleft)

{

cleft -= w[sort[i]];

b += p[sort[i]];

i++;

}

if (i < ARRAY_LENGTH)

{

b += p[sort[i]] / w[sort[i]] * cleft;

}

return b;

}

double bbKnapsack()

{

int i = 0; //从0层开始

double bestp = 0.0;

double up = bound(0);

while(i != ARRAY_LENGTH)

{

double wt = cw + w[sort[i]];

if (wt <= c) //左儿子节点为可行节点

{

if (bestp < (cp+p[sort[i]]))

{

bestp = cp + p[sort[i]];

}

TreeNode *node = new TreeNode();

initNode(*node, up, (cp+p[sort[i]]), (cw+w[sort[i]]), i+1); queue.addTail(*node);

}

up = bound(i+1);

if (bestp <= up) //右儿子节点

{

TreeNode *node = new TreeNode();

initNode(*node, up, cp, cw, i+1); queue.addTail(*node);

}

TreeNode tnode = queue.removeMax();

cout<

cw = tnode.weight; cp = tnode.profit; up = tnode.upperProfit; i = tnode.level;

}

return bestp;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值