小奥的学习笔记

  • Home
  • Learning & Working
    • Speech Enhancement Notes
    • Programming language
    • Computer & DL
    • MOOC
  • Life
    • Life Time
    • Thinking & Comprehension
    • Volunteer
    • Plan
    • Travel
  • Footprints
  • GuestBook
  • About
    • About Me
    • 个人履历
    • 隐私策略
  1. 首页
  2. Study-notes
  3. Programming language
  4. Algorithm
  5. 正文

算法笔记之回溯法(2)

2019年2月27日 1055点热度 0人点赞 0条评论

着色问题

问题分析

假设地图共有7个区域,分别是A/B/C/D/E/F/G,对上面顺序进行编号,每个区域用一个结点表示,相邻的区域有连线,那么地图就转化成一个无向连接图。

算法设计

  1. 定义问题的解空间。图的m着色问题解空间形式为n元组{x1,x2,...,xi,...,xn},每个分量取值为1,2,3,...,m,即问题的解是一个n元向量。由此可得,问题的解空间为{x1,x2,...,xi,...,xn},其中显约束为xi=1,2,...,m。
  2. 确定解空间的组织结构:一颗满m叉树,树的深度为n。
  3. 搜索解空间
    • 约束条件:假设当前扩展结点位于解空间树的第t层,那么从第1到第t-1层的结点情况都已经确定,接下来是按照扩展结点的第一个分支进行扩展,此时需要判断是否将第t个结点着色情况。第t个结点的色号要与前t-1个结点中与其有边相连的结点颜色不同,如果有颜色相同的,则第t个结点不能用这个色号,换下一个色号尝试。
    • 限界条件:无。
    • 搜索过程:扩展结点沿着第一个分支扩展,判断约束条件,满足则进入深一层继续搜索;如果不满足,则扩展生成的结点被剪掉,换下一个色号尝试。如果所有色号都尝试完毕,该结点变成死结点,向上回溯到距离其最近的活结点,继续搜索。搜索到叶子结点时,找到一种着色方案,搜索过程直到全部活结点变成死结点为止。

解题过程

地图7个区域,3种颜色。
1. 开始搜索第1层(t=1)。扩展A结点第一个分支,首先判断是否满足约束条件,因为之前还未着色任何结点,所以满足约束条件,扩展该分支,令1号结点着1号色,即x[1]=1,生成B。
2. 拓展B结点(t=2)。扩展第一个分支x[2]=1,首先判断2号结点是否和前面已经确定色号的结点(1号)有边相连且色号相同,不满足约束条件,剪掉该分支,然后沿着x[2]=2扩展,2号结点和前面已经确定色号的结点(1号)有边相连,但色号不同,满足约束条件,扩展该分支,令x[2]=2。
3. 扩展C结点(t=3)。扩展第一个分支x[3]=1,首先判断3号结点是否和前面已经确定色号的结点(1、2号)有边相连且色号相同,不满足约束条件,剪掉该分支;同理剪掉x[3]=2分支。然后沿着x[3]=3扩展,3号结点和前面已经确定色号的结点(1、2号)有边相连,但色号不同,满足约束条件,扩展该分支,令x[3]=3。生成D。
4. 扩展D结点(t=4)。扩展第一个分支x[4]=1,首先判断4号结点是否和前面已经确定色号的结点(1、2、3号)有边相连且色号相同,不满足约束条件(4余1相连),剪掉该分支;然后令x[4]=2,符合条件,生成E。
5. 扩展E结点(t=5)。扩展第一个分支x[5]=1,首先判断4号结点是否和前面已经确定色号的结点(1、2、3号)有边相连且色号相同,确定5与2、3、4相连但色号不同,满足约束条件,扩展该分支,生成F。
6. 扩展F结点(t=6)。扩展第一个分支x[6]=1,同理不满足,剪掉分支;然后沿着x[6]=2扩展,6与5号有边相连但色号不同,故满足约束条件,扩展该分支,令x[6]=2,生成G。
7. 扩展G结点(t=7)。扩展第一个分支x[7]=1,剪掉x[7]=1和x[7]=2的分支,然后令x[7]=3,符合要求,生成H。
8. 扩展H结点(t=8)。t>n,找到一个可行解,输出该可行解{1,2,3,2,1,2,3},回溯到最近的活结点G。
9. 重新扩展G结点(t=7)。G已经考察完毕,成为死结点,回溯到最近的活结点F。
10. 继续搜索,又找到第二种着色方案,输出可行解{1,3,2,3,1,3,2}。
11. 继续搜索,又找到4个可行解。

代码实现

//约束条件
bool isRight(int t)
{
    for (int j = 1; j < t; j++)
    {
        if (map[t][j])
        {
            if (x[j] == x[t])
                return false;
        }
    }
    return true;
}

//回溯方法函数
void Backtrack(int t)
{
    if (t > n)
    {
        sum++;
        cout << "第" << sum << "种方案:";
        for (int i = 1; i <= n; i++)//输出该着色方案
        {
            cout << x[i] << " ";
        }
        cout << endl;
    }
    else {
        for (int i = 1; i <= m; i++)
        {
            x[t] = i;
            if (isRight(t))
                Backtrack(t + 1);
        }
    }
}

算法复杂度分析

  1. 时间复杂度:O(nmn)。
  2. 空间复杂度:O(n)。

n皇后问题

问题介绍

在n×n的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋规则,皇后可以攻击与之在同一行、同一列、同一斜线上的棋子。现在在n*n的棋盘上放置n个皇后,使其不受攻击。

问题分析

求解策略:
以行为主导:
- 在第1行第1列放置第一个皇后。
- 在第2行放置第2个皇后。第2个皇后的位置不能和前面的皇后同列、同斜线,不用再判断同行了,因为每行我们本来就只放一个。
- 在第3行放置第3个皇后。第3个皇后的位置不能和前面的皇后同列、同斜线。
- ……
- 在第t行放置第t个皇后。第t个皇后的位置不能和前面的皇后同列、同斜线。
- ……
- 在第n行放置第n个皇后。第n个皇后的位置不能和前面的皇后同列、同斜线。

算法设计

(1)定义问题的解空间。n皇后问题解的形式为n元组:{x1,x2,...,xi,...,xn},分量xi表示第i个皇后放置在第i行第xi列,xi取值为1,2,3,...,n。显约束为不同行。

(2)解空间的组织结构:一颗m(m=n)叉树,树深度为n。

(3)搜索解空间。
约束条件:在第t行放置第t个皇后时,第t个皇后的位置不能和前t-1个皇后同列、同斜线。第i个皇后和第j个皇后不同列,即xi!=xj。

限界条件:不需要设置。

搜索过程:

从根开始,以DFS的方式进行搜索。根节点是活结点,并且是当前的扩展结点。在搜索过程中,当前的扩展结点沿纵深方向移向一个新结点,判断该新结点是否满足隐约束。如果满足,则该新结点成为活结点,并且成为当前的扩展结点,继续深一层的搜索;如果不满足,则换到该新结点的兄弟结点继续搜索;如果新结点没有兄弟结点,或其兄弟结点已全部搜索完毕,则扩展结点成为死结点,搜索回溯到其父结点处继续进行。搜索过程直到找到问题的根结点变成死结点为止。

代码实现

bool isPlace(int t)
{
    bool place = true;
    for (int j = 1; j < t; j++)
    {
        if (x[t] == x[j] || t - j == fabs(x[t] - x[j]))//判断列、对角线是否冲突
        {
            place = false;
            break;
        }
    }
    return place;
}

void backtrack(int t)
{
    if (t > n)
    {
        countn++;
        for (int i = 1; i <= n; i++)
        {
            cout << x[i] << " ";
        }
        cout << endl;
        cout << "---------" << endl;
    }
    else
    {//分别判断n个分支,特别注意i不要定义为全局变量,否则递归调用有问题
        for (int i = 1; i <= n; i++)
        {
            x[t] = i;
            if (isPlace(t))
                backtrack(t + 1);
            //上面说的是不冲突就进行下一行搜索
        }
    }
}

算法复杂度分析

  1. 时间复杂度:O(nn+1)。
  2. 空间复杂度:O(n)。
本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: C++ 回溯法 算法
最后更新:2019年2月27日

davidcheung

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

搜索
欢迎关注我的个人公众号
最新 热点 随机
最新 热点 随机
DEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架 奥地利匈牙利九日游旅程 论文阅读之Study of the General Kalman Filter for Echo Cancellation 小奥看房之鸿荣源珈誉府 杭州往返旅途及西溪喜来登和万怡的体验报告 2022年的第一篇碎碎念
奥地利匈牙利九日游旅程小奥看房之鸿荣源珈誉府论文阅读之Study of the General Kalman Filter for Echo CancellationDEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架
2010北京之行即将拉开帷幕 《优化阵列信号处理》学习笔记(第二章) 一年了,大家还好吗?(多图) 开学第二周 Linux基础学习第四天:C库函数和系统函数 Processing of WebRTC noise suppression
标签聚合
鸟哥的linux私房菜 python学习 生活 linux Python leetcode 算法 高中 学习 Java
最近评论
davidcheung 发布于 5 个月前(02月09日) The problem has been fixed. May I ask if you can s...
tk88 发布于 5 个月前(02月07日) Hmm is anyone else having problems with the pictur...
cuicui 发布于 8 个月前(10月20日) :wink:
niming 发布于 9 个月前(09月19日) 同级校友,能刷到太巧了
davidcheung 发布于 2 年前(08月16日) 我得找一下我之前整理的word文档看一下,如果找到了我就更新一下这篇文章。
Nolan 发布于 2 年前(07月25日) 您的笔记非常有帮助。贴图不显示了,可以更新一下吗?
davidcheung 发布于 3 年前(06月19日) 到没有看webrtc的代码。现在主要在看我们公司的代码了。。。只是偶尔看一看webrtc的东西。。。
aobai 发布于 3 年前(03月13日) gain_change_hangover_ 应该是每三个block 只能够调整一次,这样保证每帧...
匿名 发布于 5 年前(12月30日) 烫
小奥 发布于 5 年前(12月12日) webRTC里面的NS本身我记得就是在C++里面呀

COPYRIGHT © 2025 小奥的学习笔记. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

陕ICP备19003234号-1

鲁公网安备37120202000100号