N皇后

5 篇文章 0 订阅
2 篇文章 0 订阅

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

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

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,

该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例
在这里插入图片描述

由题目的意思我们可以知道皇后与皇后之间不可能在同一行或者同一列。所以每一行肯定有一个且只有一个皇后。所有皇后的状态数有 8!种,再结合其他的条件来选择合适的状态。由此很明显想到了回溯法。虽然有点暴力但是AC啦。下面上AC的代码:

bool isok(int row,int a[]){    //判断第row行的col列(a[row])是否可以放皇后
    for(int i=0;i<row;i++)    //col列符合条件返回true,否则返回false
      if(a[i]==a[row]||fabs(a[row]-a[i])==(row-i))
      return false;   //数组 a[]是存储每一行放皇后的col列位置
  return true;    //a[0]表示第0行皇后位置,a[n-1]代表第n-1行皇后位置
}
void queen(int row,int n,vector<vector<string> > &ss,vector<string> &s,string s1,int a[]){  // 递归回溯法
    if(row==n)   //若row==n,意味前面已经放置好n个皇后了,此时的 s代表一种皇后摆法
    {
     ss.push_back(s);  //把s 导入ss 中
     s.pop_back();   //把最后一行的元素再取出来,判断有没有其他成功的可能
    }
    else{   //若row!=n,不断的递归寻找
    int col;  //列
    for(col=0;col!=n;col++){
     a[row]=col;  //假设第row行放皇后位置为col
     if(isok(row,a)){  //判断皇后是否可以放置这个 col,不能就什么也不做,col++
     s1[a[row]]='Q';   //否则再深一层的进去寻找下一行的皇后位置
     s.push_back(s1);   //把该行可以放皇后的col记录进 s中
     s1[a[row]]='.';   //string仍然变回初始状态
     queen(row+1,n,ss,s,s1,a);   //寻找下一行的皇后 col
     }
    }
    if(row==0&&col==n);  //当row==0,col==n时意味着遍历全部结束,不需要做任何的操作。
    //PS:刚开始漏了这个判断,程序一直崩溃。找了好久bug终于发现这里有问题。
    else
    s.pop_back(); //如果这一行找不到皇后的位置,意味着上一行放皇后的位置不正确,删除上次进入 s的记录
  }   
}
class Solution {
public:
    vector<vector<string> > solveNQueens(int n) {
       vector<vector<string> > ss;
       vector<string> s;
       string s1="";
       int a[n];
       for(int i=0;i<n;i++)  //先把一行全部的str变为为全' . '
           s1=s1+".";
       queen(0,n,ss,s,s1,a);
       return ss;
    }
};
static auto _=[]()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    return 0;
}();

在这里插入图片描述

PS:因为当时漏判断一个条件,导致空的vector可以再次pop_back() , 因此程序崩溃 ,找了一段时间才发现原因,补上判断条件就AC了。

如果代码有什么错误,欢迎大家指出!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值