回溯法经典问题——N皇后问题、子集和数问题、图着色问题(哈密顿环)

一、解空间树结构

深度优先遍历——回溯法

广度优先遍历——分支限界法

二、剪枝函数

2.1 约束函数 —— 剪去 不含可行解

        2.1.1显式约束 解空间

        2.1.2隐式约束 找出所有可行解

2.2 限界函数 —— 剪去 不含最优解

三、经典问题

1.N皇后问题

1.xi != xj              //不同行不同列

2.|i - j| != |xi - xj|  //不放对角线

int place(int j)
{
    for (i = 1; i < j; i++)    
        //保证不同行不同列,且不在对角线
        if (abs(j - i) == abs(x[j] - x[i]) || x[j] == x[i])
            return 0;
    return 1;
}

void queen(int t) // 放第t个皇后
{
    if (t > n)
        sum++; // 可行解个数加1
    else
        for (int j = 1; j <= n; j++)
        {
            x[t] = j; // 第t个皇后放在第j列
            if (place(t))
                queen(t + 1);
        }
}

 2.n皇后问题的表格

 

2.子集和数问题

i j k

i:已装入

j:下一个要考虑的下标

k:剩余元素之和

条件:

1.i + wj <= M 不能超过总数

2.i + k >= M  不能剩余的加起来够不到总数

3.图着色问题

四色定理:一张地图至少需要四种颜色进行着色  可以保证相邻两个国家颜色不同

  • 哈密顿环,找一笔能够画到底的问题

 有哈密顿环:

 

无哈密顿环:

下面给出关键步骤的代码:

对应的解空间是一棵m叉树子集树,高度为n,层次i从1开始。

当顶点i与顶点j有边时,置a[i][j]=1,其他情况置 a[i][j]=0。

bool is_notSame(int i) // 判断顶点i是否与相邻顶点着色不同
{
    for (int j = 1; j <= n; j++)
        // a[i][j] == 1 有边,意思是相邻
        // && x[i] == x[j] 即相邻且同色 返回false
        if (a[i][j] == 1 && x[i] == x[j])
            return false;
    return true;
}

// 求解图的m着色问题
void dfs(int i) 
{
    if (i > n)   // 达到叶子结点
        count++; // 着色方案数增1
    else
    {
        for (int j = 1; j <= m; j++) // 试探每一种着色
        {
            x[i] = j;    // 试探着色j
            if (is_notSame(i)) // 不同色,可以着色j,进入下一个顶点着色
                dfs(i + 1);
            x[i] = 0; // 回溯
        }
    }
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值