八皇后(回溯法)

题目内容

  • n*n的矩阵,作为棋盘,放置n个皇后,且它们都无法攻击其他皇后,求出放置方法
  • 皇后的攻击方式,沿行、列、对角线都可以攻击其它皇后

基本思想

使用回溯法(穷举法)

所有的回溯问题都是由三个步骤组成:choose、explore、unchoose

因此对每个问题需要知道:

  1. choose what?   对于这个问题,我们选择每个字符串
  2. how to explore?对于这个问题,我们对剩余的字符串做同样的事情。
  3. unchoose           做相反的操作选择

回溯法步骤

1.Define helper(),通常我们需要在回溯问题中使用辅助函数,以接收更多参数

2.parameters:通常我们需要以下参数:

(1)要处理的对象

(2)指示正在处理的部分

(3)阶段性步骤结果,记住当前选择choose然后取消选择unchoose

(4)最终的结果,记住最终的结果

3.Base case:基本案例。定义何时将步骤结果添加到最终结果中以及何时返回

4.Use for-loop:通常需要一个for循环迭代输入,以便我们可以选择所有选项

5.Choose:在这个问题中,如果s的子串是回文,我们将它添加到步骤中

6.Explore:在这个问题中,我们想对剩余的内容做同样的事情,所以我们递归调用我们的函数

7.Un-Choose:我们退回,删除所选的方案,以尝试其他选项

具体步骤

  1. 从每一行开始判断,顺序在当前行的列放入Queen,并判断Queen是否合法 (choose)
  2. 重复上述步骤,向下面的行走 (explore)
  3. 若当前行没有放入Queen的合法位置,则回退 (unchoose)
  4. 回退操作直到找到当前Queen的另一个合法位置,否则一直向上面的行回退
  • choose

  

  • choose

    

  • unchoose

  

  • choose

  

  • 重复以上步骤
// 辅助函数,实现回溯法的三个步骤
void helper(vector<String> res, char[][] board, int rowIndex){
    // 如果到最后一行,返回结果
    if(rowIndex == board.length){
        res.add(generate(board));
        return;
    }
    // 依次对当前行的每列位置判断是否能放Queen
    for(int colIndex = 0; colIndex < board.length; colIndex++){
        if(isValid(board, rowIndex, colIndex)){
            // 确定当前行Queen的位置
            board[rowIndex[colIndex]] = ‘Q‘;
            // 确定完当前行的Queen之后,转到下一行,确定Queen的故事
            helper(res, board, rowIndex + 1);
            // 确定完Queen的位置后,对其他位置填 ‘.‘
            board[rowIndex][colIndex] = ‘.‘;
        }
    }
}
// 判断位置是否合法
bool bollean isValid(char[][] board, int rowIndex, int colIndex){
    // 由于从第一行开始向下走,只需要判断当前行的列以及对角线的左上和右上是否有可攻击的Queen
    // 判断列是否有可攻击的Queen
    for(int i = 0; i < rowIndex; i++){
        if(board[i][colIndex] == ‘Q‘){
            return false;
        }
    }
    // 判断对角线上是否有可攻击的Queen
    // 左上
    for(int i = rowIndex - 1, i < colIndex - 1; i >= 0 && j >= 0; i--, j--){
        if(board[i][j] == ‘Q‘){
            return false;
        }
    }
    // 右上
    for(int i = rowIndex - 1, i < colIndex + 1; i >= 0 && j < board.length 0; i--, j++){
        if(board[i][j] == ‘Q‘){
            return false;
        }
    }
    return true;
}
// 将board初始化为 ‘.‘
void init(char[][] board){
    for(int i = 0; i < board.length; i++){
        for(int j = 0; j < board.length; j++){
            board[i][j];
        }
    }
}
// 生成一个解
vector<String> generate(char[][] board){
    vector<String> res;   string s1();    int totalnums = sizeof(board) / sizeof(char);   int rows = sizeof(board[0]) / sizeof(char);int cols = totalnums / rows;
    for(int i = 0; i < rows; i++){      for(int j = 0; j < cols; j++){      s1 += board[i][j]    }   }   res.push_back(s1);
}
int main(){   int n = 8;
    vector<vector<String>> res;
    char[][] board = new char[n][n];
    init(board);
    helper(vector<vector<String>> res , char[][] board, rowIndex);   // 输出 res
    return 0;
} 

原文地址:https://www.cnblogs.com/YC-L/p/12098855.html

时间: 2024-11-07 04:33:40

八皇后(回溯法)的相关文章

八皇后回溯计算法研究

仔细看了下百度中的回溯法介绍,这是一种非常有用的算法,大概有两种模式,一种是遍历,一种是递归. 我把这两种方法都列出来了,按网上的说法,递归效率要比遍历快很多,我这里测试是一样的,可能是网络上那些遍历法根本没优化好吧, 多遍历了很多东西. 网上并没有Delphi的原代码,我综合了各种算法,将N阶皇后的算法一并写出来了.以下是原代码,希望有意研究的朋友跟我留言: //工程文件:Queen8.dpr,以下代码在Delphi2010下编译通过. program Queen8; uses  Forms,

八皇后回溯递归 40行不到

个人感觉代码还算精简,比较容易混淆的一点是,board[] 数组,数组下表指的是八皇后棋盘的行,数组下标对应的值指的是八皇后棋盘的列,至于abs()可以去百度,是一个求绝对值的函数 #include <iostream> using namespace std ; #define N 8 static int sum = 0 ; const int max = N ; void print (int board []) { for(int i = 0 ;i < max ;i++) { c

八皇后92

#include <stdlib.h>   #include <stdio.h>       int m[8][8] = {0};//表示棋盘,初始为0,表示未放置皇后   int num = 0;//解数目     //对于棋盘前row-1行已放置好皇后   //检查在第row行.第column列放置一枚皇后是否可行    bool check(int row,int column)    {        if(row==1) return true;        int i

八皇后问题(回溯法&amp;枚举法)

作者 : 卿笃军 本文讨论了八皇后问题的三种解决方案: 一.枚举法 二.回溯法(递归版) 三.回溯法(非递归版) 本来这些代码是以前编写好的,没有发表,由于最近又学习到了八皇后问题,自己整理了一下发表了出来! 首先.说明一下何为八皇后问题,我也不去谷歌了,直接简单的说明一下: 八皇后问题,就是在一个8*8的平面棋盘上,要求你摆放8个棋子,要求:这8个棋子不能有2个在同一行,也不能有2个在同一列,同时一条斜线上面也不能有2个~~~~ 比如:4*4的棋盘,你可以这样摆放(4皇后问题): 以上图为参照

八皇后问题-回溯法(matlab)

1.问题描述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上. 2.matlab代码 function PlaceQueen(row,stack,N)%回溯法放置皇后 if row>N PrintQueen(N,stack);%打印棋盘 else for col=1:N stack(row)=col; if row==1||Conflict(row,col,N,stack)%检测是

回溯法与八皇后问题

tail recursion 函数在调用的时候,会提前创建一个栈空间,给传递的参数也分配空间,当函数结束返回上层函数的时候,一些局部变量需要从栈中弹出并恢复到调用子函数之前的值,返回到上一个函数调用子函数之前的现场.如果是尾递归,从子函数返回的时候这个函数同时也会结束了,所以没有必要恢复一些局部变量,直接把局部变量的栈空间删除.因此一个尾递归的函数根本不需要使用栈来给子函数变量空间,可以直接使用当前变量的值为新参数的值. backtracking 八皇后问题 用一个类Queens表示棋盘上现在的

ACM:回溯法,八皇后问题,素数环

(一)八皇后问题 (1)回溯法 #include <iostream> #include <string> #define MAXN 100 using namespace std; int tot = 0, n = 8; int C[MAXN]; void search(int cur) { if(cur == n) ++tot; //递归边界,只要走到了这里,所有皇后必然不冲突 else for(int i = 0; i < n; ++i) { int ok = 1; C

八皇后解法(回溯法)

package com.company; /** * Created by Administrator on 2016/9/15. */public class EigthQueue { private static int N = 8; private int count = 0; // 总方案数 private int[] flag = {-1, -1, -1, -1, -1, -1, -1, -1}; //回溯法递归实现八皇后问题 //输出棋盘 private void printChes

八皇后问题——递归+回溯法

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果. 求解过程: 采用遍历的办法,就是采用将每种情况都验证的办法最终找出问题的解,但是蛮力遍历的话,需要遍历的数据量太大,计算时间花费太大,所以在遍历

javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题

赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支构成这两个结点之间的路径. ② 路径长度:结点路径上的分支数目称为路径长度. ③ 树的路径长度:从树根到每一个结点的路径长度之和. 以下图为例: A到F :结点路径 AEF : 路径长度(即边的数目) 2 : 树的路径长度:3*1+5*2+2*3=19: ④ 结点的带权路径长度:从该结点的到树的根结