採用優先隊列式分枝限界法求解0/1揹包問題-算法設計與分析報告C/C++版

設計如下

 

這個pdf文檔有點長,截圖分段了,需要可以直接下載該文檔

代碼如下

//author:rgh
//採用優先隊列式分枝限界法求解0/1揹包問題
#include <stdio.h>
#include <queue>
using namespace std;
#define MAXN 20						//最多可能物品數
//問題表示
int n=3,W=30;
int w[]={0,16,15,15};				//重量,下標0不用
int v[]={0,45,25,25};  				//價值,下標0不用
//求解結果表示
int maxv=-9999;						//存放最大價值,初始爲最小值
int bestx[MAXN];					//存放最優解,全局變量
int total=1;						//解空間中結點數累計,全局變量
struct NodeType						//隊列中的結點類型
{	int no;							//結點編號
	int i;							//當前結點在搜索空間中的層次
	int w;							//當前結點的總重量
	int v;							//當前結點的總價值
	int x[MAXN];					//當前結點包含的解向量
	double ub;	//上界
};
void bound(NodeType &e)			//計算分枝結點e的上界
{
	int i=e.i+1;
	int sumw=e.w;
	double sumv=e.v;
	while ((sumw+w[i]<=W) && i<=n)
	{	sumw+=w[i];				//計算揹包已裝入載重
		sumv+=v[i];				//計算揹包已裝入價值
		i++;
	}
	if (i<=n)	
		e.ub=sumv+(W-sumw)*v[i]/w[i];
	else
		e.ub=sumv;
}
void EnQueue(NodeType e,queue<NodeType> &qu)	//結點e進隊qu
{
	if (e.i==n)					//到達葉子結點
	{
		if (e.v>maxv)			//找到更大價值的解
		{
		maxv=e.v;
			for (int j=1;j<=n;j++)
				bestx[j]=e.x[j];
		}
	}
	else qu.push(e);			//非葉子結點進隊
}
void bfs()							//求0/1揹包的最優解
{
	int j;
	NodeType e,e1,e2;				//定義3個結點
	queue<NodeType> qu;				//定義一個隊列
	e.i=0;							//根結點置初值,其層次計爲0
	e.w=0; e.v=0;
	e.no=total++; 
	for (j=1;j<=n;j++)
		e.x[j]=0;
	bound(e);						//求根結點的上界
	qu.push(e);	//根結點進隊
	while (!qu.empty())				//隊不空循環
	{
		e=qu.front(); qu.pop();		//出隊結點e
		if (e.w+w[e.i+1]<=W)		//剪枝:檢查左孩子結點
		{
			e1.no=total++; 
			e1.i=e.i+1;				//建立左孩子結點
			e1.w=e.w+w[e1.i];
			e1.v=e.v+v[e1.i];
			for (j=1;j<=n;j++)		//複製解向量
				e1.x[j]=e.x[j];
			e1.x[e1.i]=1;
			bound(e1);				//求左孩子結點的上界
			EnQueue(e1,qu);			//左孩子結點進隊操作
		}
		e2.no=total++;				//建立右孩子結點
		e2.i=e.i+1;
		e2.w=e.w; e2.v=e.v;
		for (j=1;j<=n;j++)			//複製解向量
			e2.x[j]=e.x[j];
		e2.x[e2.i]=0;
		bound(e2);					//求右孩子結點的上界
		//輸出右孩子
		printf("輸出右孩子  e2.no=%d,e2.i=%d,e2.ub=%f\n", e2.no,e2.i,e2.ub) ;
		if (e2.ub>maxv)				//若右孩子結點可行,則進隊,否則被剪枝
			EnQueue(e2,qu);
	}
}
int main()
{
	bfs();					//調用隊列式分枝限界法求0/1揹包問題
	printf("分枝限界法求解0/1揹包問題:\n  X=[");	//輸出最優解
	for(int i=1;i<=n;i++)
	printf("%2d",bestx[i]);		//輸出所求X[n]數組
	printf("],裝入總價值爲%d\n",maxv);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章