恋上数据结构回溯 | N皇后问题
Posted 结构化思维wz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了恋上数据结构回溯 | N皇后问题相关的知识,希望对你有一定的参考价值。
N皇后问题
8皇后问题
❓ 在 8*8 的棋盘上,摆放八个皇后,使其不能互相攻击:任意两个皇后不能处于同一行、列、对角线上。 问有多少种摆法?
回溯解法
首先,缩小问题范围(4皇后问题),理解回溯的思想:
剪枝:
根据限制条件,发现同一行同一列、对角线不能摆放皇后,可以进行剪枝操作。
package 回溯;
/**
* @ClassName: Quen
* @Description: 八皇后问题
* @author: WangZe
* @date: 2022/3/14 14:40
*/
public class Queens
public static void main(String[] args)
new Queens().placeQueens(8);
/**
* 数组索引是行号,数组元素是列号,用来记录皇后的位置
*/
int[] cols;
/**
* 有多少中摆法
*/
int ways;
/**
* 思路:回溯+剪枝
* @param queenCount 皇后数量
*/
public void placeQueens(int queenCount)
if(queenCount < 1)return;
cols = new int[queenCount];
//从第0行开始摆放
place(0);
System.out.println(ways);
/**
* 从第row行开始摆放皇后
* @param row 行
*/
public void place(int row)
//如果到row==n 说明已经摆完了
if(row == cols.length)
ways++;
return;
for (int col = 0; col < cols.length; col++)
//如果位置能摆放皇后
if(isValid(row,col))
//在第row行,第col列摆放皇后
cols[row] = col;
//摆放好后,开始下一行
place(row+1);
/**
* 剪枝函数,判断第row行,第col列是否合法
* @param row
* @param col
* @return
*/
public boolean isValid(int row,int col)
for (int i = 0; i < row; i++)
//列有皇后
if(cols[i] == col)
return false;
//斜线有皇后
//(row - i)/(col-cols[i]) == 1 or -1;斜率为1or-1,代表处于同一斜线
if(row - i == Math.abs(col - cols[i]))
return false;
return true;
如何显示具体摆放位置呢???
package 回溯;
/**
* @ClassName: Quen
* @Description: 八皇后问题
* @author: WangZe
* @date: 2022/3/14 14:40
*/
public class Queens
public static void main(String[] args)
new Queens().placeQueens(4);
/**
* 数组索引是行号,数组元素是列号,用来记录皇后的位置
*/
int[] cols;
/**
* 有多少中摆法
*/
int ways;
/**
* 思路:回溯+剪枝
* @param queenCount 皇后数量
*/
public void placeQueens(int queenCount)
if(queenCount < 1)return;
cols = new int[queenCount];
//从第0行开始摆放
place(0);
System.out.println(queenCount+"皇后的摆放有几种摆法? "+ways);
/**
* 从第row行开始摆放皇后
* @param row 行
*/
public void place(int row)
//如果到row==n 说明已经摆完了
if(row == cols.length)
ways++;
show();
return;
for (int col = 0; col < cols.length; col++)
//如果位置能摆放皇后
if(isValid(row,col))
//在第row行,第col列摆放皇后
cols[row] = col;
//摆放好后,开始下一行
place(row+1);
/**
* 剪枝函数,判断第row行,第col列是否合法
* @param row
* @param col
* @return
*/
public boolean isValid(int row,int col)
for (int i = 0; i < row; i++)
//列有皇后
if(cols[i] == col)
return false;
//斜线有皇后
//(row - i)/(col-cols[i]) == 1 or -1;斜率为1or-1,代表处于同一斜线
if(row - i == Math.abs(col - cols[i]))
return false;
return true;
/**
* 打印摆法
*/
public void show()
for (int row = 0; row < cols.length; row++)
for (int col = 0; col < cols.length; col++)
if(cols[row] == col)
System.out.print("1 ");
else
System.out.print("0 ");
System.out.println();
System.out.println("---------------------");
回溯的过程分析
在剪枝方法中,添加打印语句,观察整个回溯过程:
public boolean isValid(int row,int col)
for (int i = 0; i < row; i++)
//列有皇后
if(cols[i] == col)
System.out.println("["+row+"] ["+col+"] = false");
return false;
//斜线有皇后
//(row - i)/(col-cols[i]) == 1 or -1;斜率为1or-1,代表处于同一斜线
if(row - i == Math.abs(col - cols[i]))
System.out.println("["+row+"] ["+col+"] = false");
return false;
System.out.println("["+row+"] ["+col+"] = true");
return true;
4皇后其中一次的过程:
以上是关于恋上数据结构回溯 | N皇后问题的主要内容,如果未能解决你的问题,请参考以下文章