N皇后问题
题目大意
经典问题,N个皇后放在N*N的棋盘,互不攻击。
思路
回溯,每行放一个,O(N!)
格子合法的判断
数组
?
列位置
col
[N]
?
左右对角线
lr
[2*N-1]
?
右左对角线
rl
[2*N-1]
y-x+n-1
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
屏蔽位
row
1 | 0 | 1 | 0 | 1 | 0 |
1 | 1 | 1 | 0 | 1 | 0 |
1 | 1 | 1 | 0 | 1 | 0 |
ld
1 | 0 | 0 | 1 | 0 | 0 |
1 | 1 | 0 | 1 | 0 | 0 |
1 | 0 | 1 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 1 | 1 |
0 | 1 | 0 | 1 | 1 | 1 |
0 | 0 | 1 | 0 | 1 | 1 |
*图片来源于Matrix67的Blog
代码
数组判断格子合法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
typedef __int64 LL;
#define N 14
int col[N],lr[2*N-1],rl[2*N-1];
int cnt;
int dfs(int *a,int k,int n){
int i;
if(k==n){
cnt++;
/*if(cnt < 10) {
for(i=0;i<n;i++) printf("%d ",a[i]);
printf("\n");
}*/
}
else{
for(i=0;i<n;i++){
if(!col[i] && !lr[i-k+n-1] && !rl[k+i]){
a[k] = i;
col[i] = lr[i-k+n-1] = rl[k+i] = 1;
dfs(a,k+1,n);
col[i] = lr[i-k+n-1] = rl[k+i] = 0;
}
}
}
}
int main(){
int a[N];
time_t begin,end;
begin = clock();
dfs(a,0,14);
printf("%d\n",cnt);
end = clock();
printf("time:%.3f\n ",(end - begin)*1.0/CLOCKS_PER_SEC);
return 0;
}
利用屏蔽位
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
typedef __int64 LL;
int cnt = 0;
void dfs(int *a,int k,int n,int c,int l,int r){
int i,mask,t;
if(k==n){
cnt++;
/*if(cnt < 10) {
for(i=0;i<n;i++) printf("%d ",a[i]);
printf("\n");
}*/
}
else{
mask = c | l | r;
for(i=0;i<n;i++){
t = 1<<i;
if(~mask&t){
a[k] = i;
dfs(a,k+1,n,c|t,(l|t)<<1,(r|t)>>1);
}
}
}
}
int main(){
int a[20];
time_t begin,end;
begin = clock();
dfs(a,0,14,0,0,0);
printf("%d\n",cnt);
end = clock();
printf("time:%.3f\n ",(end - begin)*1.0/CLOCKS_PER_SEC); //296
return 0;
}