首页 > 其他 > 详细

回溯法的总结

时间:2020-12-12 23:30:24      阅读:50      评论:0      收藏:0      [点我收藏+]

回溯法的总结


? 回溯法的解空间树主要包含\(n\)叉树、排列树、子集树。

? 例如在回溯法求解\(N\)皇后问题时,采用\(n\)叉树的结构,如下图所示:
? 技术分享图片

? 该解空间即为\(n\)叉树的情况,当\(x_1\)选择\(1\)时,即进入第一个分支,进而在通过剪枝函数判断,当前分支是否有可能为最优解,若为可能产生最优解则展开第一个分支;若不可能,则剪去该分支。依次递归下去对\(x_2, x_3, ...\)分别求解,当到达最后树的叶子结点,即表示这种情况可行,就可以进行后续操作,包括保存路径或保存最优解等。
? 当一条分支执行完毕后,退出当前递归,即返回上一层的状况,这就需要我们将进入分支时,对数据的修改撤回,体现在BackTrack1(t + 1);代码前后的对称性。这样就能确保从第一条分支递归结束,返回根节点再执行第二条分支时,数据恢复到根节点最初的数据。
? 最大团问题求解时,该特点明显,如下:

void BackTrack(int i) {
    if (i > n) {
        for (int j = 1; j <= n; j++)
            bestx[j] = x[j];
        bestn = cn;
        return ;
    }
    int ok = 1;
    for (int j = 1; j < i; j++)
        if (x[j] == 1 && a[i][j] == 0) {
            ok = 0;
            break;
        }
    if (ok) {
        x[i] = 1;
        cn++;
        BackTrack(i + 1);
        cn--;
    }
    if (cn + n - i > bestn) {
        x[i] = 0;
        BackTrack(i + 1);
    }
}

? 可以发现在\(17\)行中BackTrack(i + 1);的前后代码是对称的,cn++在退出递归时,进行了cn--撤销了对cn的操作。而x[i] = 1;由于每次递归时都需要重新赋值,因此无需写出其对称代码。
? 9~13行即为剪枝函数,将结点与已成团的结点不相连的分支直接剪去,不进行递归访问,提高搜索效率。20~23为限界函数,要求右子树中,剩下的所有结点数和以及抱团的结点数大于当前最优解数,这样才有可能有更好的解,进行递归访问,

? 总得来说,回溯法主要是遍历问题的所有可行解,将所有的解构成树的解空间,在通过剪枝函数和限界函数,剪去错误的分支,降低无效的搜索,以此提高搜索效率。

回溯法的总结

原文:https://www.cnblogs.com/toughtful/p/14127093.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!