分支限界法
实验要求
1 理解分支限界算法的广度优先搜寻原理及一般应用,掌握两种广度优先搜索方法
l 队列
l 优先队列
2 编程实现典型分支限界算法,理解“分支”、“限界”思想,并对算法进行验证分析。
实验内容
分支限界法0-1背包问题
示例输入(规定物品数量为10,背包容量为50,输入为20个数,前十个为物品重量,后十个数为物品价值):
12
3
11
5
6
8
9
4
7
10
6
2
7
3
2
9
8
10
4
5
示例输出(最大价值):
44
源代码
//科目:算法设计
//题目:分支限界法0-1背包问题
//语言:C++
//作者:武叶
//创作时间:2012年4月24日
#include<iostream>
#include<stack>
using namespace std;
#define N 100
class
HeapNode
//定义HeapNode结点类
{
public:
double
upper,price,weight;
//upper为结点的价值上界,price是结点所对应的价值,weight为结点所相应的重量
int
level,x[N];
//活节点在子集树中所处的层序号
};
double MaxBound(int i);
double Knap();
void AddLiveNode(double up,double cp,double cw,bool ch,int level);
stack<HeapNode>
High;
//最大队High
double
w[N],p[N];
double
cw,cp,c=50;
//cw为当前重量,cp为当前价值,定义背包容量为50
int
n=10;
//货物数量为10
int main()
{
int i;
for(i=1;i<=n;i++)
cin>>w[i]; //输入10个物品的重量
for(i=1;i<=n;i++)
cin>>p[i];
//输入10个物品的价值
cout<<Knap()<<endl;
//调用knap函数 输出最大价值
return 0;
}
double MaxBound(int j)
//MaxBound函数求最大上界
{
double
left=c-cw,b=cp;
//剩余容量和价值上界
while(j<=n&&w[j]<=left)
//以物品单位重量价值递减装填剩余容量
{
left-=w[j];
b+=p[j];
j++;
}
if(j<=n)
b+=p[j]/w[j]*left;
//装填剩余容量装满背包
return b;
}
void AddLiveNode(double up,double cp,double cw,bool ch,int lev)
//将一个新的活结点插入到子集数和最大堆High中
{
HeapNode be;
be.upper=up;
be.price=cp;
be.weight=cw;
be.level=lev;
if(lev<=n)
High.push(be);
//调用stack头文件的push函数
}
double Knap()
//优先队列分支限界法,返回最大价值,bestx返回最优解
{
int i=1;
cw=cp=0;
double
bestp=0,up=MaxBound(1);
//调用MaxBound求出价值上界,best为最优值
while(1)
//非叶子结点
{
double wt=cw+w[i];
if(wt<=c)
//左儿子结点为可行结点
{
if(cp+p[i]>bestp) bestp=cp+p[i];
AddLiveNode(up,cp+p[i],cw+w[i],true,i+1);
}
up=MaxBound(i+1);
if(up>=bestp)
//右子数可能含最优解
AddLiveNode(up,cp,cw,false,i+1);
if(High.empty()) return bestp;
HeapNode node=High.top();
//取下一扩展结点
High.pop();
cw=node.weight;
cp=node.price;
up=node.upper;
i=node.level;
}
}