n皇后

n皇后位运算版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long sum=0, upperlim=1;

void test(long row, long ld, long rd)
{
if (row!=upperlim) //row表示为表示对应行的列是放置,放置了放1,没放置放0;
{
long pos = upperlim & ~(row | ld | rd); //可以放置的列的位置,对应位为0,
while (pos) //pos为0 皇后没有地方可放,回溯;
{
long p=pos&-pos; //取得可以放皇后的最右边的列,其余bit置0
pos-=p; //将最后边的列置为0,为下一次选可放置的列做准备,后面并没有用
//其用途用于循环判断以及求出下一个p ----我的注释
test(row+p, (ld+p)<<1,(rd+p)>>1); //row ,ld,rd的新的值记录用于排除下一行禁忌列;
}
}
else
sum++;
}

int main(int argc, char *argv[])
{
int n;
scanf("%d",&n);
upperlim = (upperlim << n) - 1; //移位减一,让可以放皇后的所有的行的存储列的位置置为1;
test(0, 0, 0);
printf("%d\n", sum);
return 0;
}

回溯法

  • 用数组c[row]表示第row行放置在第i列,check()函数检查是否满足条件,满足则放置下一行,否侧继续循环找到可放置的解或者回溯
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include<iostream>
    #include<algorithm>

    using namespace std;

    int total = 0;
    int n;
    int c[17];

    int check(int cow){
    for(int i = 0; i < cow; i++){
    if(c[cow] == c[i]||abs(c[cow] - c[i]) == cow - i)
    return 0;
    }
    return 1;
    }
    int queen(int cow){
    if(cow == n) total++;
    else{
    for(int i = 0; i < n; i++){
    c[cow] = i;
    if(check(cow))
    queen(cow+1);
    }
    }
    return 0;
    }

    int main(){
    cin >> n;
    queen(0);
    cout << total;
    return 0;
    }
------ The Happy Ending ------