LeetCode:51. N-Queens(N 皇后问题)- Python

51. N皇后

问题描述:

n皇后问题研究的是如何将n个皇后放置在n×n的棋盘上,并且使皇后彼此之间不能相互攻击。
在这里插入图片描述
上图为 8 皇后问题的一种解法。

给定一个整数n,返回所有不同的 n皇后问题的解决方案。

每一种解法包含一个明确的n皇后问题的棋子放置方案,该方案中 Q. 分别代表了皇后和空位。

示例:

输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]

问题分析:

该有多无聊,才去重新写一个n年前的算法题目?这个第一次见是上数据结构课,递归的那一章,哈哈。总结一下:

(1)方法是回溯法,具体就是深度优先搜索。

(2)我们一行一行的放下去,在放的过程中,判断这个位置是否可以放?可以就放,不可以就进行下一个位置,到头了,就回溯到上一行。

(3)放完n个皇后,就输出一组结果。直到结束。

Python3实现:

方法一,递归的方法:

# @Time   :2019/02/02
# @Author :LiuYinxing
# 回溯法,递归


class Solution:
    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        res, q = [], [-1] * n   # cnt 用计数,q用于已经放的位置,例如q[2]=3 表示第3行的放到了第4个位置

        def dfs(k, n):
            if k == n:
                tmp = []
                for i in range(n):  # 输出一个结果
                    s = ''
                    for j in range(n):
                        s += 'Q' if q[i] == j else '.'
                    tmp.append(s)
                res.append(tmp)
            else:
                for j in range(n):  # 一行一行的进行深度搜索
                    if self.place(k, j, q):
                        q[k] = j
                        dfs(k+1, n)
        dfs(0, n)
        return res

    def place(self, k, j, q):  # 判断该位置是否可以放一个棋子
        for i in range(k):
            if q[i] == j or abs(q[i]-j) == abs(i-k):  # 不同列,不同斜线
                return 0
        return 1


if __name__ == '__main__':
    solu = Solution()
    print(solu.solveNQueens(4))

方法二,栈的方法(这段 C++ 代码是很久之前学数据结构时候的,这里只提供思路):

#include <iostream>
#include <cmath>
using namespace std;
#define MaxSize 100	
int count=1;                          //记录解个数	
struct StType                         //定义顺序栈类型
{	
	int data[MaxSize];	               //data[i]存放第i个皇后的列号
	int top;			               //栈顶指针
};				           
bool place(StType st,int i,int j)      //测试(i,j)是否与1~i-1皇后有冲突
{
	int k=1;
	if (i==1) 
		return true;	               //放第一个皇后时没有冲突
	while (k<=i-1)			           //j=1到k-1是已放置了皇后的列
	{
		if ((st.data[k]==j) || (abs(j-st.data[k])==abs(k-i)))
			return false;
		k++;
	}
	return true;
}
void queen(int n)					 //求解n皇后问题
{
	int i,j,k;
	bool find;
	StType st;						 //定义栈st
	st.top=0;						 //初始化栈顶指针
	st.top++;						 //将(1,1)进栈
	st.data[st.top]=1;
	while (st.top>0)				 //栈不空时循环
	{
		i=st.top;					 //当前皇后为第i个皇后
		if (st.top==n)				 //所有皇后均放好,输出一个解
		{
			cout<<n<<"皇后问题第"<<count++<<"个解为:";
			for (k=1;k<=st.top;k++)
				cout<<"("<<k<<" "<<st.data[k]<<")"<<" ";
            cout<<endl;
		}
		find=false;
		for (j=1;j<=n;j++)
			if (place(st,i+1,j))	//在i+1行找到一个放皇后的位置(i+1,j)
			{
				st.top++;
				st.data[st.top]=j;  //在i+1行找到一个放皇后的位置(i+1,j)并进栈
				find=true;          //如果为真,则返回继续,再此查找
				break;
			}
		if (find==false)			//在i+1行找不到放皇后的位置,回溯
		{
			while (st.top>0)
			{
				if (st.data[st.top]==n)	            //退栈
					st.top--;
				for (j=st.data[st.top]+1;j<=n;j++)	//在i行查找下一个位置
					if (place(st,st.top,j))
					{
						st.data[st.top]=j;
						break;
					}
				if (j>n)				//当前皇后在本行没有可放的位置
					st.top--;			//退栈
				else					//本行找到一个位置后退出回溯
					break;
			}
		}
	}
}

int main()
{
	int n;						//n存放实际皇后个数
	cout<<"温馨提示输入的数尽量不要大于15否则CPU会累死的。"<<endl;
	cout<<"请输入N皇后问题的N(N<20)值:"<<endl;
	cin>>n;
	if (n>20)
		cout<<"N值太大,本程序无法为你求解。"<<endl;
	else
	{	cout<<n<<"皇后问题求解如下:"<<endl;
		queen(n);
        cout<<endl;
	}
	return 0;
}

声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。

题目链接:https://leetcode-cn.com/problems/n-queens/

展开阅读全文

没有更多推荐了,返回首页