0x09算法设计与分析复习(二):算法设计策略-分枝限界法2
参考书籍:算法设计与分析——C++语言描述(第二版)
算法设计策略-分枝限界法
带时限的作业排序
问题描述
对于单机处理机的带时限作业排序问题,如果每一个作业具有相同的处理时间,则可以用贪心法求解。如果每个作业的处理时间允许不同,带时限的作业排序问题可描述为:设有n个作业和一台处理器,每个作业所需的处理时间、要求的时限和收益可用三元组
分枝限界法求解
带时限的作业排序问题的解结构可以采用固定大小元组或者可变大小元组。
下面采用可变大小元组
如果采用带上下界函数的分枝限界法求解,必须设计上下界函数。设X是状态空间树上的一个结点,
结点X的下界函数值定义为:
结点X的上界函数可以定义为:
综上所定义的上下界函数必定满足:
带时限的作业排序算法
//带时限的作业排序
struct Node{
//状态空间树的结点结构
Node(Node* par, int k)
{
parent=par;
j=k;
}
Node* parent;//指向该结点的双亲结点
int j;//该结点代表的解分量x[i]=j
};
template<class T>
struct qNode{
//活结点表中的活结点结构
qNode(){}
qNode(T p,T los, int sd,int k,Node *pt)
{
prof=p;
loss=los;
d=sd;
ptr=pt;
j=k;
}
T prof,loss;//当前结点X的下界函数\hat{c}(X)=loss,上界函数u(X)=24-prof
int j,d;//当前活结点所代表的解的分量x[i]=j,d是迄今为止的时间
Node *ptr;//指向状态空间树中相应的结点
};
template<class T>
class JS{
public:
JS(T *prof,int *de,int *time,int size);
T JSFIFOBB();//求最优解值
void GenerateAns(int *x,int &k);//根据函数JSFIFOBB所生成的状态空间树,产生问题的最优解(x[0],x[1],...,x[k])
private:
T *p,total;//p为收益数组,total初值为n个作业收益之和
int *t,*d,n;//t为作业处理时间数组,d为按非减次序排列的作业时限数组
Node *ans,*root;//root指向状态空间树的根,ans指向最优解答案结点
};
template<class T>
T JS<T>::JSFIFOBB()
{
//要求作业事先已按时限的非减次序排列
//函数返回最优解值
Node *E,*child;
Queue<qNode<T>> q(mSize);//生成一个FIFO队列实例q
E=root=new Node(NULL,-1);//构造状态空间树的根结点root
qNode<T> ep(0,0,0,-1,root),ec;//ep为扩展结点
T U=total+epsilon;//上界变量U赋初值,total为作业收益和,epsilon为小量
while(1){
T loss=ep.los, prof=ep.prof;
E=ep.ptr;
//loss为已造成的损失,prof为已获利益
for(int j=ep.j+1;j<n;j++){
//考察所有孩子
if(ep.d+t[j]<=d[j] && loss<U){
child=new Node(E,j);//构造E的孩子结点
ec.prof=prof+p[j];
ec.d=ep.d+t[j];
ec.ptr=child;
ec.loss=loss;
ec.j=j;
q.Append(ec);//活结点进队列
T cost=total-ec.prof;//计算上界函数值
if(cost<U){
//修改上界变量
U=cost;
ans=child;
}
}
loss=loss+p[j];
}
do{
if(q.IsEmpty())
return total=U;
ep.q.Front();
q.Serve();//选择下一个扩展结点
}while(ep.loss >=U);
}
}
函数JSFIFOBB()
采用分枝限界法的算法框架,构造状态空间树,求最优解的值。要求作业事先已按时限的非减次序排列。
函数GenerateAns()
根据JSFIFOBB()生成的状态空间树,产生问题的最优解(x[0],x[1],…,x[k]),k是解向量长度。
0/1背包
问题描述
分枝限界法求解
0/1背包算法
旅行商问题
问题描述
旅行商问题(travelling salesperson)描述为:一个旅行商准备到n个村庄售货,他从A村出发经过其他n-1个村庄,又回到出发地A村,现要求一条最短路径,使得每个村庄都经过一次且仅经过一次。
分枝限界法求解
设有向图
旅行商问题的解是一条回路:
一个问题适合用分枝限界法求解的关键是设计有效的上下界函数。设函数