位运算轻松解决N皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给定一个整数 n,返回 n 皇后不同的解决方案的数量。

位运算轻松解决N皇后问题_第1张图片

先理解N皇后问题,就是当前皇后所占位置的行与列,以及主对角线,次对角上都不能有其他皇后,如下图
位运算轻松解决N皇后问题_第2张图片
所以每放置一个皇后后,都会增加新的限制条件

    int size;//可以放皇后的位置总数
    int count;//统计有多少总方式摆放
    public int totalNQueens(int n) {
        //表示n个皇后需要n个位置来存放,1<
        //如果是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);
      }
  }

如有什么问题下方留言,看到会尽快回复

你可能感兴趣的:(后端)