当前位置:   article > 正文

回溯法—N皇后问题—java实现_n皇后问题回溯法java排列数

n皇后问题回溯法java排列数

问题描述:

    要求在一个n×n的棋盘上放置n个皇后,使得它们彼此不受攻击。

    按照国际象棋的规则,一个皇后可以攻击与之同一行或同一列或同一斜线上的任何棋子。

    因此,n皇后问题等价于:要求在一个n×n的棋盘上放置n个皇后,使得任意两个皇后不在同一行或同一列或同一斜线上。


一个皇后的攻击范围:

                                    


n皇后的解空间—完全n叉树:


                        


    要找出“四皇后”问题的解,最可靠的方法就是把各种情况都分析一遍,将符合条件的解找出来。但这样做十分地费时间。

采用回溯算法进行求解,在搜索的过程中,将不满足条件要求的分支树剪去,可以有效地降低算法的时间复杂度


首先定义一个Location类,用来表示棋盘上(实际上就是一个二维数组)点的位置:

  1. static class Location{
  2. int x;//对应棋盘的行
  3. int y;//对应棋盘的列
  4. Location(int x,int y){
  5. this.x = x;
  6. this.y = y;
  7. }
  8.                 //重写toString函数用来输出点的信息
  9. public String toString() {
  10. return "(" + x + "," + y + ")";
  11. }
  12. }



然后就是判断两个皇后放置的位置是否冲突,需要判断是否在同一行、同一列和同一斜线上,这里所有的符合要求的皇后都放置在一个Location链表中,如果要新加入一个皇后,就必须要与当前链表中所有的皇后都进行冲突比较,如果冲突就放弃这个方案;如果不冲突,继续下一步,直到N个皇后都存在于链表中,才算得到了一个解:

  1. /**
  2. * 判断位置为loc的皇后是否合法
  3. */
  4. private static boolean isLegalLoc(LinkedList<Location> list, Location loc) {
  5. for(Location each : list){
  6. if(loc.x == each.x || loc.y == each.y) //判断是否在同一行或同一列
  7. return false;
  8. else if (Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y)) //判断是否在同斜线上
  9. return false;
  10. }
  11. return true;
  12. }

核心算法:

  1. /**
  2. * 主要函数,用回溯法。
  3. */
  4. private static void NQueen(LinkedList<Location> list, int x, int y) {
  5. if(list.size() == SIZE){ //当list元素个数为SIZE时,表示SIZE个皇后都摆放完毕,打印后即可退出函数。
  6. printLocation(list); //打印皇后摆放方式
  7. return ;
  8. }
  9. for(int i = x ; i < SIZE ; i++){
  10. Location loc = new Location(i, y);
  11. if(isLegalLoc(list, loc)){
  12. list.offer(loc); //将第y行的皇后摆放好
  13. NQueen(list, 0, y+1); //开始摆放y+1行的皇后,同样从第0列开始摆放
  14. list.pollLast(); //每次摆放完一个皇后后,都要将其撤回,再试探其它的摆法。
  15. }
  16. }
  17. }



由于皇后的攻击范围的特性,在这个算法执行时,只用考虑一行或者一列的情况就行,即要么使x=0固定,让y从0到n-1进行;要么反过来让y=0固定,让x从0到n-1进行。这样可以省去很多不必要的比较。

全部代码(其中还包括将N皇后问题的解显示输出的函数):

  1. package quene;
  2. import java.util.LinkedList;
  3. import java.util.Scanner;
  4. public class Com_quene {
  5. private static int SIZE = 0;//皇后的个数
  6. private static int count = 0;//记录摆放的方式数
  7. public static void main(String[] args) {
  8. // TODO Auto-generated method stub
  9. Scanner input = new Scanner(System.in);
  10. System.out.println("请输入你要解决几个皇后的问题");
  11. SIZE = input.nextInt();
  12. input.close();
  13. LinkedList<Location> list = new LinkedList<Location>();
  14. NQueen(list, 0, 0); //从棋盘的第0行第0列开始
  15. System.out.println(SIZE + "皇后共有 " + count + "种摆放方式");
  16. }
  17. static class Location{
  18. int x;//对应棋盘的行
  19. int y;//对应棋盘的列
  20. Location(int x,int y){
  21. this.x = x;
  22. this.y = y;
  23. }
  24. public String toString() {
  25. return "(" + x + "," + y + ")";
  26. }
  27. }
  28. /**
  29. * 主要函数,用回溯法。
  30. */
  31. private static void NQueen(LinkedList<Location> list, int x, int y) {
  32. if(list.size() == SIZE){ //当list元素个数为SIZE时,表示SIZE个皇后都摆放完毕,打印后即可退出函数。
  33. printLocation(list); //打印皇后摆放方式
  34. return ;
  35. }
  36. for(int i = x ; i < SIZE ; i++){
  37. Location loc = new Location(i, y);
  38. if(isLegalLoc(list, loc)){
  39. list.offer(loc); //将第y行的皇后摆放好
  40. NQueen(list, 0, y+1); //开始摆放y+1行的皇后,同样从第0列开始摆放
  41. list.pollLast(); //每次摆放完一个皇后后,都要将其撤回,再试探其它的摆法。
  42. }
  43. }
  44. }
  45. /**
  46. * 判断位置为loc的皇后是否合法
  47. */
  48. private static boolean isLegalLoc(LinkedList<Location> list, Location loc) {
  49. for(Location each : list){
  50. if(loc.x == each.x || loc.y == each.y) //判断是否在同一行或同一列
  51. return false;
  52. else if (Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y)) //判断是否在同斜线上
  53. return false;
  54. }
  55. return true;
  56. }
  57. /**
  58. * 打印皇后摆放方式
  59. * @param list
  60. */
  61. private static void printLocation(LinkedList<Location> list) {
  62. String[][] show = new String[SIZE][SIZE];
  63. for(int i = 0;i<SIZE;i++) {
  64. for(int j = 0;j<SIZE;j++) {
  65. show[i][j] = "0";
  66. }
  67. }
  68. for(Location each : list){
  69. System.out.print(each.toString() + "\t");
  70. show[each.x][each.y] = "1";
  71. }
  72. System.out.println();
  73. for(int i =0;i<SIZE;i++) {
  74. for(int j=0;j<SIZE;j++) {
  75. System.out.print(show[i][j] + " ");
  76. }
  77. System.out.println();
  78. }
  79. System.out.println();
  80. count ++;
  81. }
  82. }


四皇后问题解的示例:




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/633313
推荐阅读
相关标签
  

闽ICP备14008679号