算法学习——回溯法

回溯法是一种通过深度优先搜索解决问题的方法,它构造部分解并逐步扩展。解空间可以表示为子集树或排列树,根据问题选择合适的形式。解题步骤包括定义解空间、选择搜索结构、剪枝以避免无效搜索。文章通过n皇后问题和0-1背包问题展示回溯法的应用。
摘要由CSDN通过智能技术生成

回溯法的实质

回溯法可看作穷举法的一种实现方式

 

计算过程

每步只构造一个部分节并立即对此部分解进行评估。若此部分解有可能拓展为“所求解”,则继续扩展;反之此部分解不可能扩展为所求解,则继续尝试其他部分解。直到穷尽一切可能。

 

解空间与解空间树

描述回溯法时,可有两种解空间树选择。一是子集树,一是排列树。

解空间:所有可能的解构成的集合。

解空间树:将解空间组织成树结构。

子集树:每个解(x1,....,xn)的每个分量xi的值取自于一个集合Si,解空间大小为2的n次方;

排列树:每个解(x1,...,xn)都是集合S的全排列。解空间大小为n!

一般情况下,子集树优于排列树,因为n! >> 2的n次方(题目要采取哪种解空间,要具体视情况而定)

 

解题步骤

1)针对所给问题,定义问题的解空间;

2)确定易于搜索的解空间结构;

3)以深度优先方式搜索解空间树,并在搜索过程中用剪枝函数避免无效搜索。

 

框架

t:表示递归深度,即当前扩展节点在解空间树中的深度。

output():纪录或输出结果的函数

constaint():约束函数。返回值=true,则满足约束条件;返回值=false,可剪去相应子树。

bound():限界函数。返回值=true,目标函数未越界,可用backtak(t+1)进一步搜索;返回值=false,可剪去相应子树。

一、子集树

1.递归回溯子集树的一般算法

        void backtrack(int t){
            if(t > n){ 
                output(x);
            }else {
                for(int i = 0;i <= 1;i++){
                    x[t] = i;
                    if(constraint(t) && bound(t)){
                        backtrack(t+1);
                    }
                }
            }
        }

 

2.递归回溯排列树的一般算法

因为是排列树,所以相当于当前的数不断地和后面的数交换,得到新的排列。

        void backtrack(int t){
            if(t > n){
                output(x);
            }else {
                for(int i = t;i < n;i++){
                    swap(x[t],x[i]);
                    if(constraint(t) && bound(t)){
                        backtrack(t+1);
                    }
                    swap(x[t],x[i]);
                }
            }
        }

 

例子

1、n皇后问题

描述:在nx格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行/同一列/同一斜线上的棋子。n后问题等价于在nxn格的棋盘上放置n个皇后,任何2个皇后不放在同一列/同一行/同一斜线。

 

解法一:


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值