题目描述: 把 n 个皇后无伤放进n * n的棋盘上。
输出要求:按字典序输出前三个放置方案中第1~n行的皇后的列数构成的序列。
思路:
核心难点在于如何记录前一个状态用于回溯。
如果我们采用一个n * n的矩阵记录第 i 行第 j 列的格子是否被场上皇后控制,我们必须要记录有几个皇后能控制这个格子(二维int数组),否则回溯的时候会出问题,因为其他皇后可能仍然控制着这个格子。这就造成了巨大的内存开销。
我们敏锐地注意到,其实并不需要记录每个格子是否被控制,因为每一行每一列每一条斜线都只能存在一个皇后。换言之,我们只需要记录每一行每一列每一条斜线是否被控制就可以了。第 i 行有没有被控制不需要考虑,因为我们就是基于行数进行回溯的。其他三种情况可以采用下列方法记录:
① 第 j 列:是很好记录的,使用一维bool数组c[ j ]。
② 斜率为正的斜线:y - x = k(k = -(n - 1),……,1,2,……,n - 1),一共是2n - 1条。我们敏锐地注意到,截距 k 唯一标识了一条斜线。那么,我们可以用一维bool数组x2[k + n],即x2[y - x + n]来记录。(加 n是为了让数组下标为正)
③斜率为负的斜线:y + x = k(k = -(n - 1),……,1,2,……,n - 1),一共是2n - 1条。同理②,我们可以用一维bool数组x1[ k ],即x1[y + x]来记录。
#include<iostream> #include<cstring> using namespace std; int n; int temp[105], tot, l, con; bool c[105], x1[105], x2[105]; void Find(int st) { if(st > n) { tot++; if(con<3) { con++; for(int i = 1; i <= n; i++) { if(i > 1) cout<<" "; cout<<temp[i]; } cout<<endl; } return ; } for(int i = 1; i <= n; i++) if(!c[i] && !x1[st + i] && !x2[st - i + n]) { c[i] = 1; x1[st + i] = 1; x2[st - i + n] = 1; temp[++l] = i; Find(st + 1); --l; c[i] = 0; x1[st + i] = 0; x2[st - i + n] = 0; } } int main() { cin>>n; Find(1); cout<<tot; return 0; }回溯
标签:记录,int,斜线,Challenge,Checker,bool,皇后,P1219,105 From: https://www.cnblogs.com/nightfury/p/16877880.html