算法——八皇后问题(eight queen puzzle)之回溯法求解
八皇后谜题是经典的一个问题,其解法一共有种!
其定义:
- 首先定义一个8*8的棋盘
- 我们有八个皇后在手里,目的是把八个都放在棋盘中
- 位于皇后的水平和垂直方向的棋格不能有其他皇后
- 位于皇后的斜对角线上的棋格不能有其他皇后
- 解出能将八个皇后都放在棋盘中的摆法
这个问题通常使用两种方法来求解:
- 穷举法
- 回溯法(递归)
本文章通过回溯法来求解,回溯法对比穷举法高效许多,让我们学习如何实现吧!
实现思想:
- 我们先在棋盘的第0行第1个棋格放下第一个皇后
- 下一行寻找一个不冲突的棋格放下下一个皇后
- 循环第2步
- 如果到某一行全部8个格子都无法放下皇后,回溯到前一行,继续寻找下一个不冲突的棋格
- 把8个皇后都放在棋盘之后,输出或存储摆法,结束
实现(Java)算法:
定义棋盘
我们通过一个二维整型数组表示一个棋盘
数组内为1是放下了的皇后,0则是空白的棋格
我们下下面定义一个方法:通过检查棋格是否为1来知道是不是有皇后
// 定义一个棋盘
static int chessboard[][] = new int[8][8];
检查冲突
这个方法用来检查冲突:在水平垂直方向、斜角上的棋格有无其他皇后,传入的(x,y)是需要检查的棋格,如检查棋格(1,0)即棋盘的第2行第1个,是否能放下皇后。
// 检查是否符合规则
private static boolean checked(int x,int y){
for(int i = 0;i<y;i++){
// 检查水平垂直方向
if(chessboard[x][i]==1)return false;
// 检测左斜角
if((x-y+i>=0)&&chessboard[x-y+i][i]==1)return false;
// 检查右斜角
if((x+y-i<=7)&&chessboard[x+y-i][i]==1)return false;
}
return true;
}
放下皇后
我们在每一行都执行以下步骤,通过从第1个棋格到第8个遍历寻找可以放下皇后的棋格
如果放下了皇后,我们就可以继续放下下一个了,将行数+1,我们递归调用这个方法
public static boolean solve(int y){
// 将一行的8种情况都扫描一次
for(int i = 0;i<8;i++){
// 每次检测前都将当前行清空,避免脏数据
for(int k = 0;k<8;k++)chessboard[k][y]=0;
if(checked(i, y)){
chessboard[i][y] = 1;
// 当前一行已经获得解法,进入下一行
solve(y+1);
}
}
return false;
}
算法边界
当我们放下了所有8个皇后后,需要一个终止条件,我们在行数y=8时,结束算法
同时你可以输出一个棋盘摆法了!恭喜你已经把这个经典问题解决了!
// 当y=8时,已经找到一种解决方法
if(y == 8){
return true;
}
以下是完整的算法
public class EightQueen{
// 定义一个棋盘
static int chessboard[][] = new int[8][8];
// 计数器
static int count = 0;
// 解题方法
public static boolean solve(int y){
// 当y=8时,已经找到一种解决方法,计数器加一并输入摆法
if(y == 8){
System.out.println("solved!");
show();
count++;
return true;
}
// 将一行的8种情况都扫描一次
for(int i = 0;i<8;i++){
// 每次检测前都将当前行清空,避免脏数据
for(int k = 0;k<8;k++)chessboard[k][y]=0;
if(checked(i, y)){
chessboard[i][y] = 1;
// 当前一行已经获得解法,进入下一行
solve(y+1);
}
}
return false;
}
// 检查是否符合规则
private static boolean checked(int x,int y){
for(int i = 0;i<y;i++){
// 检查垂直方向
if(chessboard[x][i]==1)return false;
// 检测左斜角
if((x-y+i>=0)&&chessboard[x-y+i][i]==1)return false;
// 检查右斜角
if((x+y-i<=7)&&chessboard[x+y-i][i]==1)return false;
}
return true;
}
// 输出棋盘摆法
public static void show(){
for(int i = 0;i<8;i++){
for(int j = 0;j<8;j++){
System.out.print(chessboard[j][i]+" ");
}
System.out.println("");
}
}
}
在执行这个算法后:
have 92 ways to sovle it!
我们获得了92种棋盘摆法!
算法——八皇后问题(eight queen puzzle)之回溯法求解的更多相关文章
- 7, java数据结构和算法: 八皇后问题分析和实现 , 递归回溯
什么是八皇后问题: 指的是,在一个8 * 8的棋盘中, 放置8个棋子, 保证这8个棋子相互之间, 不在同一行,同一列,同一斜线, 共有多少种摆法? 游戏连接: http://www.4399.com/ ...
- 54. 八皇后问题[eight queens puzzle]
[本文链接] http://www.cnblogs.com/hellogiser/p/eight-queens-puzzle.html [题目] 在8×8的国际象棋上摆放八个皇后,使其不能相互攻击,即 ...
- USACO 1.5.4 Checker Challenge跳棋的挑战(回溯法求解N皇后问题+八皇后问题说明)
Description 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子. 列号 0 1 2 3 4 5 6 ...
- 回溯法求解n皇后和迷宫问题
回溯法是一种搜索算法,从某一起点出发按一定规则探索,当试探不符合条件时则返回上一步重新探索,直到搜索出所求的路径. 回溯法所求的解可以看做解向量(n皇后坐标组成的向量,迷宫路径点组成的向量等),所有解 ...
- 回溯法——求解N皇后问题
问题描写叙述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后.使其不能互相攻击,即随意的两个皇后不能处在允许行.同一列,或允许斜线上. 能够把八皇后问题拓展 ...
- 算法设计与分析——n后问题(回溯法+位运算)
一.问题描述 在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 二.算法设计 解n后问题的回溯算法描述如下: #include ...
- 『嗨威说』算法设计与分析 - 回溯法思想小结(USACO-cha1-sec1.5 Checker Challenge 八皇后升级版)
本文索引目录: 一.回溯算法的基本思想以及个人理解 二.“子集和”问题的解空间结构和约束函数 三.一道经典回溯法题点拨升华回溯法思想 四.结对编程情况 一.回溯算法的基本思想以及个人理解: 1.1 基 ...
- 【算法导论】八皇后问题的算法实现(C、MATLAB、Python版)
八皇后问题是一道经典的回溯问题.问题描述如下:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8*8个方格),使它们谁也不能被吃掉? 看到这个问题,最容易想 ...
- 九度OJ 1140:八皇后 (八皇后问题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:795 解决:494 题目描述: 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * ...
随机推荐
- MySql插入点数据
DROP PROCEDURE IF EXISTS pre;delimiter $$ CREATE PROCEDURE pre ()BEGIN DECLARE i INT DEFAULT 1 ;WHIL ...
- Python之路【第十七篇】:Django【进阶篇 】(转自银角大王博客)
Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...
- AOP - 2 实例(SpringBoot 注解方式)
1.创建Spring Boot项目 创建一个Spring Boot 项目,然后pom中引入web 模块与AOP相关依赖. <dependency> <groupId>org.s ...
- Scanner的使用 猜数字 +猜电影
猜数字public class Main { public static void main(String[] args) { int random=(int)(Math.random()*100)+ ...
- plus.webview更新上一个页面的信息
let currentWebview = plus.webview.currentWebview(); let backWebview = currentWebview.opener(); ...
- 源码分析 ucosii/source 任务源码详细分析
分析源码: 得先学会读文档, 函数前边的 note :是了解该程序员的思想的途径.不得不重视 代码前边的 Notes,了解思想后,然后在分析代码时看他是如何具体实现的. 1. ucosii/sour ...
- Python中eval函数的作用
eval eval函数就是实现list.dict.tuple与str之间的转化str函数把list,dict,tuple转为为字符串# 字符串转换成列表a = "[[1,2], [3,4], ...
- (双指针 二分) leetcode 167. Two Sum II - Input array is sorted
Given an array of integers that is already sorted in ascending order, find two numbers such that the ...
- 野路子码农系列(2)Python中的类,可能是最通俗的解说
啥叫佩奇?啥叫类?啥叫面向对象?后面两个问题以前在大学里“祖传谭浩强”的时候我经常会有所疑问.老师说着一堆什么public, private,我都是一脸懵逼,啥叫私有?为啥要私有?然后就神游天外了…… ...
- VS Less Compiler插件使用
1.打开扩展管理器,下载安装 2.新建一个test.less文件 3.敲入代码 @grayback: #808080; body { background:@grayback; } 4.保存即可自动生 ...