• 【回溯法】八皇后问题(递归和非递归)


    先贴代码,分递归回溯法和非递归回溯法

    递归回溯法,代码如下:

    // test.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int a[9] = {0};
    int n = 8;
    int count = 0;
    
    bool check(int arr[], int n)
    {
        for (int i = 2; i <= n; ++i)
            for(int j = 1; j <= i-1; ++j)
                if (arr[i] == arr[j] || (abs(arr[i]-arr[j]) == abs(i-j)))
                    return false;
        return true;
    }
    
    void printQueens(int a[])
    {
        printf("第%d种情况:", count);
        for (int i = 1; i <= n; ++i)
            printf("%d",a[i]);
        printf("
    ");
        count++;
    }
    
    void searchQueens8(int r)
    {
        if (r > n)
            printQueens(a);
    
        for (int i = 1; i <= n; ++i)
        {
            a[r] = i;
            if (check(a, r))
            {
                searchQueens8(r+1);
            }
        }
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        searchQueens8(1);
        return 0;
    }

    非递归回溯法,代码如下:

    #pragma once
    #include "stdafx.h"
    
    const int N = 8;
    int cszStack[9];
    int sum = 0;
    int top;
    
    void printQueenStack()
    {
        printf("No.%d:", sum);
        for (int i = 1; i <= N; ++i)
            printf("%d", cszStack[i]);
        printf("
    ");
        sum++;
    }
    
    // k表示第k行
    bool judge(int k)
    {
        if (k == 1)
            return true;
    
        int i;
        for (i = 1; i < k; ++i)
        {
            if (cszStack[i] == cszStack[k])
                return false;
    
            if (abs(k-i) == abs(cszStack[k] - cszStack[i]))
                return false;
        }
    
        return true;
    }
    
    void putQueen()
    {
        top = 1;
        while(top > 0)
        {
            cszStack[top]++; // 摆放一个皇后
            // 如果第top行的皇后没有摆放出第8列,那就一直找到它在top行的合法位置
            while((cszStack[top] <= N) && (!judge(top)))
                cszStack[top]++;
    
            if (cszStack[top] <= N)
            {
                if (top == N)
                {
                    printQueenStack();
                    // 输出结果
                }
                else
                {
                    top++;
                    cszStack[top] = 0;
                }
            }
            else
            {
                // 在第top行8列全部不能放置皇后,说明前面几行的摆放不合理,所以要退回上一行
                top--;
            }
        }
    
    }
    
    void initStack()
    {
        for (int i = 0; i <= N; ++i )
            cszStack[i] = 0;
    
        sum = 0;
        top = 0;
    }
    
    void searchQueueStack()
    {
        initStack();
        putQueen();
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        //SearchQueens8(1);
    
        searchQueueStack();
        return 0;
    }

    指导思想:

    走不通,就掉头;

    检查合格才继续往下走;遇到不合格就是掉头;

    能进则进,不能进则换,不能换则退;

    解空间:一颗树空间

    扩展规则:深度优先策略

    设计过程:(1)确定问题的解空间;(2)确定结点的扩展规则;(3)搜索解空间

    退回到上一状态的过程叫做回溯,枚举下一个状态的过程叫做递归;

    回溯就像人走迷宫,先选择一个前进方向尝试,一步步试探,在遇到死胡同不能再往前的时候就会退到上一个分支点,另选一个方向尝试,而在前进和回撤的路上都设置一些标记,以便能够正确返回,直到达到目标或者所有的可行方案都已经尝试完为止。

    回溯法应用——算法说明

    (1)      八皇后问题中的核心代码

    遍历过程函数;check函数;

    (2)      解决此类问题的核心内容

    解空间树的搜索算法;估值/判断函数:判断哪些状态适合继续扩展,或者为答案状态;

    递归算法框架:

    int a[n];

    Queens(int k)

    {

    if (k > n)

           // 即表示最后一个皇后摆放完毕,输出结果;

    else

    //枚举k个皇后所有可能路径

    for (int i = 下界;I <= 上界; i++)  

    {// 依次从列顶端开始搜索,一直到列底端,直到找到合适的位置,如果未找到,自动返回上层递归

           a[k] = i;

           if (check(a,k))

                  // 递归摆放下一个皇后Queens(k+1);

    }

    }

     

    非递归算法框架:

    int a[n],i;

    初始化数据a[];

    i = 1;

    while (i > 0(有路可走)) and (未达到目标)// 还未回溯到头

    {

           if (i == n)

    搜索到一个解,输出;// 搜索到叶结点

           else

           {

                  a[i]第一个可能的值

                  while(a[i]不满足约束条件且在搜索空间内)

                         a[i]下一个可能的值;

                  if(a[i]在搜索空间内)

                  { 标识暂用的资源;i=i+1;} // 扩展下一个结点

                  else

                  {清理所占的状态空间;i=i-1;} // 回溯

    }

    }

     

    参考链接:https://wenku.baidu.com/view/d1e9d6fe02020740bf1e9bce.html?from=search

  • 相关阅读:
    Spring MVC-表单(Form)标签-单选按钮(RadioButton)示例(转载实践)
    Ubuntu 16.04中VirtualBox 5.1使用U盘/USB设备的方法
    Spring MVC-表单(Form)标签-复选框集合(Checkboxes)示例(转载实践)
    Ubuntu 16.04下减小/释放/清理VirtualBox虚拟硬盘文件的大小
    关注点分离
    谈代码注释
    DelegatingFilterProxy类的作用
    GOPS 2018全球运维大会上海站 参会感悟梳理
    Java switch case
    Android 微信网址分享添加网络图片
  • 原文地址:https://www.cnblogs.com/gwzz/p/9197445.html
Copyright © 2020-2023  润新知