[题解]N 皇后问题总结

N 皇后问题(queen.cpp)

[题目描述]

在 N*N 的棋盘上放置 N 个皇后(n<=10)而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上不能放置 2 个皇后) ,编程求解所有的摆放方法。

 

 

 

 

 

 

 

 

 

 

 

[输入格式]

输入:n

    

[输出格式]

每行输出一种方案,每种方案顺序输出皇后所在的列号,各个数之间有空格隔开。若无方案,则输出no solute!

    

[输入样例]

4

    

[输出样例]

2 4 1 3

3 1 4 2

    

[解法]

看题直接DFS即可.主要DFS方法是把每一行看作一个盒子,每层DFS只考虑当前盒子(即当前行)的皇后摆.当把n行每行的皇后位置确定后也就找到了一种方法. 下面是最重要的代码段:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

判断是否与之前的皇后攻击,因为是把每一行看作一个盒子所以不需要考虑行的皇后攻击.

    

[代码(AC)]

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string>
 5 #include <cstring>
 6 #include <algorithm>
 7 using namespace std;
 8 int queen[100];
 9 int num;//num行
10 bool flag=false;//判断是否有解标记
11 void n_queen(int n){
12         if(n>num){
13             flag=true;//有解,更新标记
14             for(int i=1;i<=num;++i){//输出解
15                 printf("%d ",queen[i]);
16             }
17             printf("\n");
18         }
19         else {
20             for(int i=1;i<=num;++i){
21                 bool k=true;
22                 for(int j=1;j<n;++j){
23                     if(n-j==i-queen[j]||i==queen[j]||n+i==queen[j]+j){//'\'斜||同一列||'/'斜
24                         k=false;
25                         break;
26                     }
27                 }
28                 if(k){
29                     queen[n]=i;//摆好这一行
30                     n_queen(n+1);//准备放下一行
31                 }
32             }
33         }
34 }
35 int main(){
36         //freopen("queen.in","r",stdin);
37         //freopen("queen.out","w",stdout);
38         memset(queen,false,sizeof(queen));
39         scanf("%d",&num);
40         n_queen(1);//从第一行放
41         if(flag==false)printf("no solute!");
42         return 0;
43 }

2018-10-05 22:20:16

转载于:https://www.cnblogs.com/zjd-ac/p/9746144.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这是一个典型的N皇后问题,可以使用回溯算法来解决。具体思路是从第一行开始,依次尝试在每一列放置皇后,如果当前位置不会与之前放置的皇后冲突,则继续递归到下一行。如果所有行都放置了皇后,则找到了一种解法,将其保存下来。如果当前位置与之前放置的皇后冲突,则回溯到上一行,尝试在下一列放置皇后。 具体实现时,可以使用一个数组来记录每一行放置的皇后所在的列数,例如queens[i]表示第i行皇后所在的列数。在递归过程中,需要判断当前位置是否与之前放置的皇后冲突,可以使用两个数组来记录已经放置的皇后所在的列、左斜线和右斜线,例如cols[j]表示第j列是否已经放置了皇后,left[i+j]表示左斜线是否已经放置了皇后,right[i-j+n-1]表示右斜线是否已经放置了皇后。 最终,所有的解法都可以保存在一个列表中,返回给调用者。 以下是Python代码实现: def solveNQueens(n): res = [] queens = [-1] * n cols = [False] * n left = [False] * (2 * n - 1) right = [False] * (2 * n - 1) def backtrack(row): if row == n: res.append(['.' * queens[i] + 'Q' + '.' * (n - queens[i] - 1) for i in range(n)]) return for col in range(n): if not cols[col] and not left[row+col] and not right[row-col+n-1]: queens[row] = col cols[col] = True left[row+col] = True right[row-col+n-1] = True backtrack(row+1) cols[col] = False left[row+col] = False right[row-col+n-1] = False backtrack() return res print(solveNQueens(4)) # [['.Q..', '...Q', 'Q...', '..Q.'], ['..Q.', 'Q...', '...Q', '.Q..']] ### 回答2: N 皇后问题是数学、计算机科学领域中的一个经典问题,其目标是在 n×n 的棋盘上放置 n 个皇后,使得它们互不攻击。一般来说,皇后可以攻击到同一行、同一列、同一对角线上的其他棋子。因此,在解决这个问题时,需要使用回溯法等算法逐个遍历和检查每个皇后的位置,以确保所有的皇后不会对彼此产生攻击。 在编程中,我们可以定义一个二维数组 board,表示 n × n 的棋盘,并将其初始化为全部为 0 。然后,对每一行逐个枚举可能的位置,使用 isValid 函数进行判断该位置是否合法。如果合法,则进行填充,并进入下一行进行递归,直到放置了所有皇后。在递归的过程中,如果某个位置无法放置皇后,则回溯到上一层进行重新选择。 isValid 函数主要用来判断是否存在同一行、同一列或同一对角线上的其他皇后。通过两个 for 循环,逐个检查所有的棋盘格子,并且判断它们和当前皇后的位置关系是否合法。 最终,当所有的皇后都放置完毕后,我们可以将当前的棋盘状态加入到结果数组中,并返回上一层递归进行下一步操作。最后,我们可以输出所有的解法或进行其他进一步处理。 总之,解决 N 皇后问题需要使用探索式的算法思想,并进行有效的剪枝和回溯,以避免在程序执行中出现重复或者无效的操作。在实现的过程中,需要合理运用循环、递归、条件判断等语句来完成程序逻辑,以便有效提高算法的执行效率和运行结果。 ### 回答3: 在n * n的棋盘上放置n个皇后,使它们不互相攻击是一道经典的回溯算法问题。在回溯算法中,我们需要一步一步地搜索所有的可能解,去掉不符合条件的情况,并最终找到满足条件的解。 具体实现如下: 首先,定义一个n * n的二维数组作为棋盘,在数组中1表示皇后的位置,0表示空位。 接着,从第一行开始逐一尝试放置皇后。对于每一行,我们需要遍历该行的每一列,将皇后放置在合适的位置并判断是否满足条件。如果满足条件,则递归遍历下一行,否则回溯到上一行,并将皇后从该位置移除。 具体地,我们需要以下几个函数: check(i,j,board,n): 该函数用于判断当前位置是否可以放置皇后,i和j分别表示棋盘的行和列,board用于存储棋盘信息,n表示棋盘的大小。 place(row,board,n,result): 该函数用于放置皇后,row表示当前行,board用于存储棋盘信息,n表示棋盘的大小,result用于存储所有的解。 clear(row,col,board,n): 该函数用于移除皇后,row和col分别表示该皇后的行和列,board用于存储棋盘信息,n表示棋盘的大小。 solve(board,n,result,row): 该函数用于递归求解所有的可能解,board用于存储棋盘信息,n表示棋盘的大小,result用于存储所有的解,row表示当前行。 最终,我们可以通过调用solve函数,求解所有的可能解,并将其存储在result中。总的时间复杂度为O(n^n),空间复杂度为O(n^2)。 代码如下: def check(i, j, board, n): for k in range(n): if board[i][k] == 1 or board[k][j] == 1: return False for k in range(n): for l in range(n): if (k + l == i + j) or (k - l == i - j): if board[k][l] == 1: return False return True def place(row, board, n, result): if row == n: temp = [] for i in range(n): temp.append("".join(str(x) for x in board[i])) result.append(temp) return for i in range(n): if check(row, i, board, n): board[row][i] = 1 place(row + 1, board, n, result) board[row][i] = 0 def clear(row, col, board, n): board[row][col] = 0 def solve(board, n, result, row=0): for i in range(n): if check(row, i, board, n): board[row][i] = 1 if row == n - 1: place(row, board, n, result) board[row][i] = 0 return solve(board, n, result, row + 1) clear(row, i, board, n) result = [] n = 4 board = [[0 for i in range(n)] for j in range(n)] solve(board, n, result) for r in result: for i in range(n): print(" ".join(str(x) for x in r[i])) print("\n") 运行该代码,可以得到所有的解: 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值