n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给定一个整数 n,返回 n 皇后不同的解决方案的数量。
先理解N皇后问题,就是当前皇后所占位置的行与列,以及主对角线,次对角上都不能有其他皇后,如下图
所以每放置一个皇后后,都会增加新的限制条件
int size;//可以放皇后的位置总数
int count;//统计有多少总方式摆放
public int totalNQueens(int n) {
//表示n个皇后需要n个位置来存放,1<<n ,
//如果是4就是10000 减一后就是01111,1表示空位,1111代表可以存4个皇后
size=(1<<n)-1;
//count表示统计有多少种方式摆放
count=0;
DFS(0,0,0);
return count;
}
//以n为4解析代码
//最开始row为0表示 0000 四个位置都还是空位
//ld为0,0000表示当前行每个的左对角线都没有被占用
//rd为0,0000表示当前行每个的右对角线都没有被占用
public void DFS(int row,int ld,int rd){
if(row==size){//表示row从0000---1111,说明4个皇后都摆放成功了
count++;//然后次数加1
return;
}
//free_Postion表示当前行可以放皇后的空位,row|ld|rd 代表当前行被占用(就是不能放置皇后)的位置
//第一次 0000|0000|0000----就是0000
//0000表示当前行都可以放置皇后;
//size 1111 1表示皇后可用的位置, ~取反是因为row,ld,rd中 1代表占用, 0没有占用,与sizez中的1111
//相反,取反后0000---1111,举例 0110,代表一行中第二个位置与第三个位置被占用了,取反后1001,就是第1
//与第四个位置没有占用,与上可以使用的空间1001 & 1111 =1001, free_Postion=1001,代表1,4空位可以放置
int free_Postion=size & (~(row|ld|rd));
while(free_Postion!=0){ //代表有空位在不为0才可以继续放置皇后
//当空位为1001时,free_Postion=1001,-free_Postion期数等于~free_Postion+1
//取反0110然后加1为0111,-free_Postion=0111与0110 等于0001 得到最右边的最低为用来放置皇后
int curr=free_Postion&(-free_Postion);
//这一步就是放置皇后 free_Postion = free_Postion-curr 等于1001-0001----1000,说明最后一位用来放置皇后
free_Postion-=curr;
//然后递继续放置皇后
// Row|curr-----0000|0001 等于0001说明下一行中右边第一位不能放置皇后
// (ld|curr)<<1 ----0000|0001等于0001 左移后 0010 ,说明下移行中第二位不能放置
// (rd|curr)>>1 ----0000|0001等于0001 右移后 0000,这是因为右对角线没有位置
//当下一次 row|ld|rd 等于0001|0010|0000 就是0011 取反后1100 说明前两个位置可以放
DFS(row|curr,(ld|curr)<<1,(rd|curr)>>1);
}
}
如有什么问题下方留言,看到会尽快回复