回溯法展开状态空间树

解空间:假设问题的解能用n元组(X1,……,Xn)表示,其中Xi取自某个有穷集Si,这些n元组构成的集合称为问题的解空间。假设集合Si的大小|Si|=mi,则解空间的大小m=m1* m2……* mn。
注意这里解空间的大小取决于元组中每个元素的可能取值的数量,从而取决于元组是如何定义的
例如:8皇后问题(在8×8的棋盘上放置8个皇后, 使得这8个皇后不在同一行、同一列及同一斜角线上. )
定义元组时,若只将8个皇后不在同一行纳入定义中,则约束条件就是8个皇后不在同一列且不在同一斜角线上。这时每个皇后占一行,且可占据一行中的任意8个列(该题认为每个皇后是一样的),则有8× 8 … ×8=88个可能,即解空间的大小是88
定义元组时,若将8个皇后不在同一行和不在同一列都纳入元组定义中,则8个皇后各占一行,任一皇后选择一列(此时该皇后位置确定),那么下一行的皇后只有7列可以选择(因为8个皇后两两不能在同一列),以此类推,最终有8× 7× …× 1=8!种可能,即解空间的大小为8!。
由于生成解空间的复杂性不能太高,所以不将第三个条件纳入元组定义中。
约束条件:简单地说,题目中所有要达成的条件,除去纳入元组定义的条件,其他的都是约束条件。约束条件在展开状态空间树时使用。

状态空间树:状态空间树是根据解空间建立的树结构,它的建立是用来尝试选择元组的各个分量。从根节点到叶子结点的一条路径对应解空间的一个元组。状态空间树的某一层的各个分支代表元组中某个分量的可能取值。
展开状态空间树就是将约束条件作为一个选择的标准,在状态空间树的基础之上,选择元组的各个分量,最终得到的元组即为满足题目所有条件的可行解。
解结点:状态空间树从根节点到该节点仅满足元组定义条件(即解空间条件)的元组,则该节点即为解结点,也就是状态空间树的叶子结点。
可行解:满足所有约束条件的元组成为可行解,说白了就是最终我们要求得的解。找到可行解就是展开状态空间树的最终目的。
答案结点:如果某一个解结点所对应的元组(即从状态空间树根节点到该解结点的这个元组(即可行解))满足约束条件,则该解结点称为答案结点。
活结点:已展开了部分子节点, 但所有子结点尚未全部展开的结点.
死结点:被限界或已展开了所有子结点的结点.
E-结点: 当前正在展开子结点的活结点.
展开状态空间树的方法:

  1. 1.深度优先展开法:相当于对状态空间树作深度优先搜索,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。抽象来说,就是一个E-结点展开自己的一个子结点后,
    就让该子结点成为E-结点的展开方法
  2. 2.回溯法:加限界(约束条件和限界函数)的深度优先展开状态空间树的方法。
  3. 3.分枝限界法:
    ◆ 队列式分枝限界法(FIFO):相当于对状态空间树进行广度优先搜索。抽象来说,每一个活结点只有一次机会成为E-结点,一旦成为E结点,它将展开他的所有子节点,自己就变成了死结点。
    ◆ 优先队列式分支限界法(最小损耗优先):按照优先队列规定的优先级选择优先级最高的结点作为E-结点。
  • 回溯法搜索解空间树时,通常采用两种策略避免无效搜索,提高回溯法的搜索效率。其一是用约束函数在当前节点(扩展节点)处剪去不满足约束的子树;其二是用限界函数剪去得不到最优解的子树。这两类函数统称为剪枝函数
  • 回溯法求问题的所有解时,要回溯到根,且根节点的所有子树都已被搜索遍才结束。
  • 回溯法求问题的一个解时,只要搜索到问题的一个解就可结束。
    回溯法解4-皇后问题
    4-皇后问题的状态空间树(这里的元组定义条件仅包含4个皇后不能在同一行和同一列,剩下的条件不能在同一斜角线上作为展开状态空间树的限界条件(这里即为约束条件))。
    在这里插入图片描述
    4-皇后问题的状态空间树
    回溯法展开状态空间树:限界条件4个皇后不在同一斜角线上,等价于|xi-xj|≠|i-j|。
    在这里插入图片描述
    在这里插入图片描述
    最终的结果:
    在这里插入图片描述
    由于这个问题不存在最优解,所以得到一个可行解(2,4,1,3)后,就不用找其他解了。
    回溯法解子集和数问题:
    题目描述:给定n个正数W(i)和另一个正数M. 找出{W(i),i=1,…,n}中所有使得和数等于M的子集. 该问题称为子集和数的判定问题。
    状态空间树左子节点对应于X(i)=1,表示要找的子集元组中包含W(i);右子节点对应于X(i)=0,表示要找的子集元组中不包含W(i)。
    限界条件ki=1W(i)X(i)+∑ni=k+1W(i)<M
    当所有正数按非递减排好序时:
    限界条件:ki=1W(i)X(i)+∑ni=k+1W(i)<M或者ki=1W(i)X(i)≠M && ∑ki=1W(i)X(i)+W(k+1)>M
    当达到该限界条件时,继续展开k结点不能得到答案结点,则停止展开k结点,回溯到父结点。
    实际应用时,S=∑k-1i=1W(i)X(i)
    展开左子节点的限界条件为:S+W(k)≠M && S+W(k)+W(k+1)>M,则停止展开左子节点,并且r-=W(k),判断是否可以展开右子节点。(注:若S+W(k)==M,则直接展开左子节点。)
    展开右子节点的限界条件为:S+r<M或者S+W(k+1)>M,则停止展开右子节点并回溯。
    若展开左子节点前限界条件不满足(即没有被限界),则展开左子节点,x(k)=1,S+=W(k),k+=1,r-=W(k)。(此时k结点成为E-结点,重复上述展开步骤)。
    若展开左子节点前限界条件不满足(即没有被限界),则展开右子结点,x(k)=0,k+=1,其他不变。(此时k结点成为E-结点,重复上述展开步骤)。
    对于限界条件S+r<M,初始时S=0,r=∑ni=1W(i),肯定满足S+r>=M,否则肯定找不到和等于M的子集,没意义。由于展开左子节点时,S和r都没变化,所以S+r的值和该节点的一样肯定满足>=M,展开有节点之前,r的值会减去一个值,S+r的值会减小,可能小于M,所以展开右节点之前要判断该限界条件,而展开左子节点前不用判断该限界条件。
例题:W(1:6)=(5,10,12,13,15,18),M=30

子集和数问题的状态空间树:
在这里插入图片描述
回溯法展开状态空间树:
初始时S=0,r=5+10+…+18=73,S+r=73>30。(对于展开左子节点只需在初始时判断该条件)
S+W(1)=0+5=5≠30,S+W(1)+W(2)=0+5+10=15<30,未被限界,展开左子节点,x(1)=1,S=S+W(1)=5,k=k+1=2,r=r-W(1)=73-5=68。
在这里插入图片描述
5+10=15≠30,5+10+12=27<30,展开左子节点,x(2)=1,S=15,k=3,r=58
在这里插入图片描述
15+12=27<30,15+12+13=40>30,不展开左子节点,r=58-12=46,判断是否能展开右子结点:15+46=61>30,15+13=28<30,展开右子结点,x(3)=0,k=4。
在这里插入图片描述
15+13=28≠30,15+13+15=43>30,不展开左子节点,r=46-13=33,判断是否展开右子结点:15+33=48>30,15+15=30,展开右子结点,x(4)=0,k=5。
在这里插入图片描述
15+15=30,展开左子节点。得到一个可行解。
在这里插入图片描述
回溯到节点(5,2,68),不断重复上述步骤,找到这个问题的所有解,最终结果:
在这里插入图片描述
回溯法解0/1背包问题:(贪心法和动态规划均有提过)
题目描述:n=3,w= [ 20 , 15 , 15 ],p= [ 40 , 25 , 25 ]且c= 30
0/1背包问题的状态空间树:
在这里插入图片描述
该问题不仅有约束函数(背包容量),还有限界函数(最优效益值bestp)。所以必须求得所有可行解,才能得到最优解。
约束函数:cw+w(k)>c,则不装入k物品。(该约束函数在展开左子节点前需判断)。若不被约束,即cw+w(k)<=c,则展开左子节点,x(k)=1,cw=cw+w(k),cp=cp+p(k);否则,判断是否能展开右子结点。
限界函数:bound(x)<=bestp,则不展开x结点。(该限界条件在展开右子结点前需判断)。若不被限界,则展开右子结点,x(k)=0;否则回溯。
cw=∑k-1i=0w(i)x(i)为前k-1个物品已装的重量
cp=∑k-1i=0p(i)x(i)为前k-1个物品的效益值
bound(k-1)=cp+其余物品的连续背包问题的优化效益值(贪心法得到)。即结点k-1对应的子问题的优化效益值的上界。
bestp是算法当前获得的最优效益值。

例题: n= 4,c= 7,p= [ 9 , 10 , 7 , 4 ],w= [ 3 , 5 , 2 , 1 ],求最优效益值。

这些对象的效益密度为[ 3 , 2 , 3 . 5 , 4 ].
按密度排列为:(4,3,1,2)
w’=[1,2,3,5],p’=[4,7,9,10]
初始bestp=-∞;bound=4+7+9+(7-1-2-3)/5×10=22;cw=0;cp=0。
cw+w(1)=0+1=1<7,展开左子节点:此时x(1)=1,cw(1)=0+1=1,cp(1)=0+4=4,bound(1)=cp(1)+(p(2)+p(3))+(c-cw(1)-w(2)-w(3))/w(4)×p(4)=20+1/5×10=22
在这里插入图片描述
1+2=3<7,展开左子节点:此时x(2)=1,cw(2)=1+2=3,cp(2)=4+7=11,bound(2)=cp(2)+p(3)+(c-cw(2)-w(3))/w(4)×p(4)=20+1/5×10=22
在这里插入图片描述
3+3=6<7,展开左子节点:此时x(3)=1,cw(3)=3+3=6,cp(3)=11+9=20.bound(3)=cp(3)+(c-cw(3))/w(4)×p(4)=20+1/5×10=22
在这里插入图片描述
6+5=11>7,停止展开左子节点,判断展开右子结点,此时bound(3)=22>bestp=-∞,展开右子结点:此时x(4)=0。
在这里插入图片描述
bound(4* )=cp(3)+0×p(4)=20>bestp=-∞,所以bestp=20。回溯到节点3,bound(2)=22>bestp,展开右子结点:此时x(3*)=0.
在这里插入图片描述
bound(3* )=cp(2)+((c-cw(2))/w(4)xp(4)=11+(7-3)/5x10=19<bestp,被限界,则不再展开6节点。回溯到节点2,bound(1)=22>bestp,展开右子结点:此时x(2* )=0.
在这里插入图片描述
bound(2* )=cp(1)+p(3)+(c-cw(1)-w(3))/w(4)xp(4)=4+9+(7-1-3)/5x10=19<bestp,被限界,不再展开7节点。回溯到节点1,bound=22>bestp,展开右子结点:此时x(1* )=0.
在这里插入图片描述
bound(1* )=7+9+(7-2-3)/5×10=20,被限界,不再展开8节点。至此,得到了该问题的解(也就是最优解)[1,1,1,0],回到排序前即[1,0,1,1],最优效益值为20.

为什么
0/1背包问题的限界条件bound<=bestp在展开左子右子时都得判断;
而子集和数问题限界条件S+r<M只在展开右子时要判断?
拿展开i节点来说:
**对于子集和数问题:**展开i结点的右子(展开i结点的右子说明第i个值不会被作为元组解的一个分量)前,r值要减去W(i),此时会造成上界值减小甚至可能会导致S+r<M,这时就不用再继续展开i节点了。这就是为什么展开右子前要作这个限界分析。
由于展开i的左子后,子节点i+1的r-=W(i),S+=W(i),S+r的值等于它的父节点i的S+r值,由于既然可以展开到i结点,则i结点的S+r肯定>=M,可以继续展开左子而不用判断该条件。(详细解释:若该结点i作为父节点的左子节点,则继续找父节点的父节点,直到找到个父节点(b)是作为他的父节点(a)的右子,我们知道a可以展开右子肯定是满足S+r>=M,即b结点不被限界,可以继续展开,后面子节点的S+r值都和b一样也不被限界,所以我们才说展开左子时不用判断该限界条件;若不断往上找父节点没有作为右子的父节点,则会一直到根节点,展开根节点前肯定会判断S+r与M的关系,若小于M,则这个题就没有意义,若大于等于M,则不被限界,可以展开,而作为他的左子节点自然也不会被限界,一直到左子i都不会被限界,所以说展开左子节点不用判断S+r<M.
**对于0/1背包问题:**与其说bound<=bestp在展开左子右子时都得判断,不如说展开作为左子的节点的左子和右子时不用判断,而展开作为右子的结点的左子和右子时都要判断。因为它与子集和数的区别在于展开右子前bound值不会变,展开后才会变。如果i结点作为左子,i的bound=i的父节点i-1的bound值,既然可以得到展开到i-1结点,那么bound肯定>bestp,所以展开i结点时不用判断该条件;若i结点是右子结点,由于i结点的父节点可以展开到i结点,则i-1肯定是S+r>=M的,i的bound值小与等于父节点i-1的bound,甚至可能小于M,从而没有继续展开结点i的必要,所以在展开作为右子的结点的左子右子时要判断该条件。但是由于一般我们不会这样区分展开作为左子的左子右子和作为右子的左子右子,所以就笼统地在展开左子和右子时都得判断。
  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值