leetcode51 N皇后问题

解决N皇后问题分为以下几个步骤:

  1. 首先要定义出两个二维的数组,
    一个是attack数组用于表示当前皇后已经占住的攻击范围,0代表可以放置皇后,1代表此地方不能放置皇后
    一个是queen用于表示哪些点上皇后有皇后,当前位置为’.'代表此位置没有皇后,当前位置为’Q’代表有皇后,然后再进行初始化:
  queen全部初始化为'.'
  attack全部初始化为0
下面写一下第一步的代码:
vector<vector<int>>attack;
vector<string>queen;
for(int i = 0; i<n;i++)//这里的n代表是n皇后问题,如果是8皇后,n为8
{
	attack.push_back(vector<int>());//这里是先插入一个占住位置,后面再用循环进行修改
	for(int j = 0; j<n;j++)
	{
		attack[i].push_back(0);
	}
	queen.push_back("");//插入一个占住位置,然后再进行修改
	queen[i].append(n,'.');//第i行插入n个'.'
}
  1. 第二个要解决的问题是皇后的插入,要专门写一个函数用于插入,然后利用两个数组dx和dy进行方向的变换,同时在插入后,attack的0也更新为1:
//x,y为要插入的皇后的位置,queen为皇后表,attack为皇后攻击表
void put_queen(int x,int y,vector<vector<int>>&attack)
{
		//x,y在围绕着皇后棋盘上的变化
		static const int xx[] = {-1,1,0,0,-1,-1,1,1};
        static const int yy[] = {0,0,-1,1,-1,1,-1,1};
        attack[x][y]=1;//皇后位置置为1
        for(int i = 0;i<attack.size();i++)//从皇后位置向1到n-1个位置延伸
        {
			for(int j = 0;j<8;j++)//8种变化方法
			{
				int dx = x + xx[j]*i;
				int dy = y + yy[j]*i;
				//当前移动的位置还在棋盘内
				if(dx >= 0 && dx < attack.size() && dy >= 0 && dy < attack.size())
				{
					attack[dx][dy] = 1;//将当前位置设置成可攻击
				}
			}
		}
}

3.下面第三步就要进行回溯了

//回溯法求解N皇后的递归函数
    /*
    k表示当前处理的行
    n表示N皇后问题
    queen存储皇后的位置
    attack标记皇后的攻击位置
    solve存储N皇后的全部解法
    */
void dfs(int k,int n,vector<string>&queen,vector<vector<int>>&attack,vector<vector<string>>&solve)
{
	if(k == n)
	{
		solve.push_back(queen);
		return;
	}
	for(int i = 0;i<n;i++)//这个n代表的是n皇后问题,其实也就是列的循环
	{
		if(attack[k][i] = 0)
		{
			vector<vector<int>>temp = attack;
			queen[k][i] = 'Q';
			put_queue(k,i,attack);
			dfs(k+1,n,queen,attack,solve);
			attack = temp;
			queen[k][i] = '.';
		}
	}
} 

完整代码:

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>>solve;
        vector<vector<int>>attack;
        vector<string>queen;
        //矩阵初始化
        for(int i = 0;i<n;i++)
        {
            attack.push_back(vector<int>());//随便添加一个行
            for(int j = 0;j<n;j++)
            {
                attack[i].push_back(0);//将每一行全部置为0
            }
            queen.push_back("");//随便添加一行
            queen[i].append(n,'.');//将这一行全部置为.
        }
        //回溯求解n皇后
        backtrack(0,n,queen,attack,solve);
        return solve;
    }
private:
    //实现在(x,y)防止函数,二维数组attack表示棋盘是否可放置皇后
    void put_queen(int x,int y,vector<vector<int>>&attack)
    {
        static const int dx[] = {-1,1,0,0,-1,-1,1,1};
        static const int dy[] = {0,0,-1,1,-1,1,-1,1};
        attack[x][y] = 1;

        for(int i = 0;i<attack.size();i++)//从皇后位置向1到n-1个位置延伸
            for(int j = 0;j<8;j++)//遍历八个方向
                {
                    int nx = x + i*dx[j];
                    int ny = y + i*dy[j];
                    if(nx >= 0 && nx < attack.size() && ny >= 0 && ny <attack.size())//在棋盘范围内
                        attack[nx][ny] = 1;
                }
    }
    //回溯法求解N皇后的递归函数
    /*
    k表示当前处理的行
    n表示N皇后问题
    queen存储皇后的位置
    attack标记皇后的攻击位置
    solve存储N皇后的全部解法
    */
    void backtrack(int k,int n,vector<string>&queen,vector<vector<int>>&attack,vector<vector<string>>&solve)
    {
        if(k == n)//找到一组解法
        {
            solve.push_back(queen);
            return;
        }
        for(int i = 0;i<n;i++)//这个n代表的是n皇后问题
        {
            if(attack[k][i] == 0)
            {
                vector<vector<int>>temp = attack;
                queen[k][i] = 'Q';
                put_queen(k,i,attack);
                backtrack(k+1,n,queen,attack,solve);
                attack = temp;
                queen[k][i] = '.';
            }
        }
    }
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值