例题四单源最短路径问题分支限界算法的数据结构
#include
#include
#include
using namespace std;
class Graphic{
int n;//图中顶点的个数
int e;//边的数目
int **adjmatrix;//邻接矩阵,存储图
int *dist;//dist[n],存储单元点到其他n-1个顶点的最短路的长度
int prev;//prev[i]=j 存储顶点i 的前驱结点为j , 利用这些前驱结点可以找到源点到顶点i的最短路
int start;//源点
public:
Graphic(int n, int e);
void ShortPath();
void display();
};
class PathNode{ //放入优先队列中的节点,解空间中的结点
int i; //解空间中结点的编号。一个结点对应于一条路
int length;//路的长度。
friend class Graphic;
public:
PathNode(int a=0, int b=0):i(a),length(b){}
bool operator <(PathNode b) const {//定义优先关系函数
return length>b.length;
}
};
Graphic::Graphic(int n, int e){
this->n=n; this->e=e;
adjmatrix=new int[n+1];
dist=new int[n+1]; prev=new int[n+1];
for(int i=1;i<=n;i++) adjmatrix[i]=new int[n+1];
cout<<“输入源点编号:”; cin>>start;
cout<<“请输入e条边”<<endl;
for(i=1;i<=n;i++){ //邻接矩阵初始化
for(int j=1;j<=n;j++)
adjmatrix[i][j]=-1; //两个顶点之间没有边
adjmatrix[i][i]=0;
}
for( i=0;i<e;i++) {
int a, b,length;
cin>>a>>b>>length; //输入一条边所依附的两个顶点和这条边的长度
adjmatrix[a][b]=length; //有向图
dist[i]=99999; //最短路赋初值
prev[i]=start;
}
};
例题六装载问题
#define NUM 100
int n; //集装箱的数量
int c; //轮船的载重量
int w[NUM]; //集装箱的重量数组
int MaxLoading(){
queue Q;
Q.push(-1);
int i = 0; //层号
int Ew = 0; //当前的装载重量
int bestw = 0;//最优装载重量
int r = 0; //剩余货物的总重量
for(int j=1; j<n; j++)
r += w[j];
while (true) {//搜索子空间树
//检查左子树
int wt = Ew+w[i];
if (wt<=c){ //检查约束条件
if (wt>bestw) bestw = wt;
if (i<n-1) Q.push(wt); //加入活结点队列
}
if (Ew+r>bestw && i<n-1) //检查右子树, 检查上界条件
Q.push(Ew);
Ew = Q.front(); //从队列中取出活结点
Q.pop();
if (Ew==-1) { //判断同层的尾部
if (Q.empty())
return bestw;
Q.push(-1); //同层结点尾部标志
Ew = Q.front(); //从队列中取出活结点
Q.pop();
i++;
r -= w[i];
}
}
return bestw;
}
例题七 0-1背包问题
优先队列元素的类
#define NUM 100
class object
{
friend int knapsack(int *,int *,int ,int);
public:
//排序运算符重载
int operator < (object a)const
{
return (ratio>a.ratio);
}
private:
int ID; //物品编号
double ratio; //单位重量价值
};
class queueNode{ //优先队列中的结点
friend class knap;
public:
//优先队列以uprofit为优先级参数
friend bool operator < (queueNode a,queueNode b)
{
if(a.uprofit<b.uprofit) return true;
else return false;
}
private:
int uprofit; //结点的价值上界
int profit; //结点相应的价值
int weight; //结点相应的重量
int level; //活结点在子集树中所处的层序号
node *ptr; //指向活结点在子集树中相应结点的指针
};
解空间树的类
class knap{
friend int knapsack (int *,int *,int ,int);
public:
int maxKnapsack();
private:
priority_queue H; //创建优先队列
int bound(int i); //计算未装入背包中的剩余物品的价值上界函数
void addLiveNode (int up,int cp,int cw,bool ch,int level); //增加活结点到子集树中,并将其插入优先队列
node *E; //指向子集树中的正在扩展的结点的指针
int c; //背包容量
int n; //物品总数
int w[NUM]; //物品重量数组
int p[NUM]; //物品价值数组
int cw; //当前装包重量
int cp; //当前装包价值
int bestx[NUM]; //最优解
例题八旅行商问题
#include
#include
using namespace std;
class Traveling{
int n;//图中顶点的个数
int e;//边的数目
int **a;//邻接矩阵(无向图的邻接矩阵)
int cc;//当前路径(子路径,非完整路径)的长度
int bestc;//当前最小费用
int NoEdge;
public:
int BBTSP();
Traveling();
};
struct node{
//优先队列以lcost为优先级参数
friend bool operator < (const node& a,const node& b){
if(a.lcost > b.lcost) return true;
else return false;
}
int lcost; //子树费用的下界
int rcost; //从x[s]~x[n-1]顶点的最小出边和
int cc; //当前费用。截止到当前城市的路径长度
int s; //当前结点的编号。结点的层次编号。已经经过的城市的数目
int *x; //需进一步搜索的路径x[s+1:n]。全排列
};
priority_queue H;
int minOut[NUM]; //各个顶点的最小出边费用
int minSum = 0; //最小出边费用之和
//计算各个顶点的最小出边费用
int i, j;
for(i=1; i<=n; i++)
{
int Min = NoEdge;
for(j=1; j<=n; j++)
if( a[i][j]!=NoEdge && (a[i][j]<Min || MinNoEdge))
Min = a[i][j];
if (MinNoEdge) return NoEdge; //无回路
minOut[i] = Min;
minSum += Min;
}
while (E.s<n) { //非叶结点
if (E.sn-1) { //当前扩展结点是叶结点的父结点
//再加2条边构成回路 //所构成的回路是否优于当前最优解
if (a[E.x[n-1]][E.x[n]]!=NoEdge && a[E.x[n]][1]!=NoEdge
&& (E.cc+a[E.x[n-1]][E.x[n]]+a[E.x[n]][1]<bestc
|| bestcNoEdge)) {
//费用更小的回路
bestc = E.cc+a[E.x[n-1]][E.x[n]]+a[E.x[n]][1];
E.cc = bestc;
E.lcost = bestc;
E.s++;
H.push(E);
}
else delete[ ] E.x; //舍弃扩展结点
}