zoukankan      html  css  js  c++  java
  • <基础><回溯>八皇后问题

    1.Intro

    这是由国际西洋棋棋手marks在1848年提出的一个问题。在8x8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行同一列或同一斜线上,问有多少种摆法。我们计算机编程来解决这个问题。

    2.Solution

    首先尝试暴力直接法,8个循环嵌套,状态空间在8^8,so huge,弃用。

    略加思考,可以用回溯来解决的奥。

    回溯backtrack是说

    result=[]
    def fuc(路径,选择列表):
      if 满足结束条件:
        result.add(路径)
      
      for 选择 in 选择列表:
        做选择
        fuc(路径,选择列表)
        撤销选择

    回溯用了递归,for循环里递归,在递归前做选择,递归调用结束后撤销选择。

    尝试使用回溯来解决八皇后问题,写代码:

    #include<bits/stdc++.h>
    using namespace std;
    short arr[8];
    int result = 0;
    bool isValid(int x,int y){
        if(x==0){
            return 1;
        }
    
        for(int i=0;i<x;i++){
            if(arr[i]==y | abs(arr[i]-y)==abs(i-x)){
                return 0;
            }
        }
        return 1;
    }
        
    void fuc(int col){
        if(col==8){
            result++;
            return;
        }
        
        for(int i=0;i<8;i++){
            if(isValid(col,i)){
                arr[col]=i;
                fuc(col+1);
            }
        }        
    }
    int main(){
        fuc(0);
        cout<<result<<endl;
        return 0;
    }

    在上面的代码中,我们秉承着这样的思路去解决问题:先看第0列,再看第1列,在看第2列一直到第7列。在每一列上放一颗皇后。

    arr[8]数组表示着棋盘的摆放情况,比如说arr[3]=6则表示(3,6)位置上有一颗皇后;

    result是计数变量,当发现一种可行方案后就给result++;

    isValid(int x,int y)函数用来判断看x列的时候如果皇后放在(x,y)位置会不会与前x-1列冲突,可以放就返回1,不可以放就返回0;

    fuc(int col)函数是主体,代表着看到第col列的时候的情况。

     从这里也可以看得出来,回溯算法其实也算是暴力穷举,复杂度较高,因为其中用到了递归速度肯定不能算快,另外它不像DP存在重叠子问题可以优化。

     emmm——————暂时只想写回溯这一种解法,可能以后还会扩充其他的吧。

    3.Extension

    好,找到了八皇后的可行解法,接下来推广到n皇后问题。

    只要把上面代码的8全换成这个n就好啦
  • 相关阅读:
    ios 将Log日志重定向输出到文件中保存
    IOS中GPS定位偏移纠正(适用于Google地图)
    java与IOS之间的RSA加解密
    [iPhone高级] 基于XMPP的IOS聊天客户端程序(IOS端一)
    [IOS] Storyboard全解析-第一部分
    NTP时间同步
    Prthon多线程和模块
    Python循环语句,对象
    Python起步学习
    Nginx实战之反向代理WebSocket的配置实例
  • 原文地址:https://www.cnblogs.com/dynmi/p/12128747.html
Copyright © 2011-2022 走看看