题意:
给定一个n*n的棋盘, 皇后只能攻击他所在那一列, 左对角线, 右对角线, 求一个所有皇后的不能互相攻击的 solution。
分析:
可以从第一行开始枚举, 然后标记该列和主副对角线, 注意点(i,j)左对角线可以标记为 i+j, 右对角线是 i +(n-j), 用3个标记数组标记即可, 回溯法指的是先试试取这个点, 然后标记, 递归回来时候不要这个点, 取消标记。
/* 回溯法 每次摆放后 都把剩下的列 左右对角线标记 然后再摆放空的位置 如果到最后或者某一行找不到空的位置 就回溯 如果找到最后一行有空的摆放位置 就是答案 */ #include<bits/stdc++.h> using namespace std; int vis[3][50] = {0};//vis[0]负责标记这一列 vis[1]负责标记左对角线 vis[2]负责右对角线 int n; int ans[20]; int ok = 0; void dfs(int row) { if(row > n)//如果能走到这里 就是答案 { ok++; if(ok <= 3) { for(int j = 1; j < row; j++) { printf("%d", ans[j] ); if(j == row - 1) printf(" "); else printf(" "); } } } else { for(int i = 1; i <= n; i++) { if(!vis[0][i] && !vis[1][i+row] && !vis[2][i+(n-row)]) //如果这个位置没有标记 { ans[row] = i;//那vis[row+1][i-1]=vis[row+1][i+1]=vis[row][i] = 1;不能放子 vis[0][i] = vis[1][i+row] = vis[2][i+(n-row)] = 1;//标记列 左对角线 右对角线; dfs(row+1); vis[0][i] = vis[1][i+row] = vis[2][i+(n-row)] = 0;//回溯的时候归零 } } } } int main() { while(scanf("%d", &n) !=EOF) { dfs(1); printf("%d ", ok); ok = 0; //printf(" "); } }