八皇后问题
代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <cmath>
using namespace std;
int p[8][8]; // 棋盘数组
int cnt; //记录解的个数
//判断(r,c)位置能否放置棋子,能,返回true,不能返回false
//因为是从第一行开始往下放棋子,所以只需要判断r行之前的行中有没有棋子使得(r,c)不可落子即可
bool can(int r, int c){
for (int i=0; i<r; i++){ //判断同一列中是否有棋子,有则返回false
if (p[i][c] == 1)
return false;
}
int rr; //临时纵座标(行数)
int rc; //临时横座标(列数)
for (int i=1; i<=r; i++){ //判断(r,c)左上方是否有棋子使(r,c)处不可落子
rr = r-i;
rc = c-i;
if (rr>=0 && rc>=0){
if (p[rr][rc] == 1)
return false;
}
}
for (int i=1; i<=r; i++){ //判断(r,c)右上方是否有棋子使(r,c)处不可落子
rr = r-i;
rc = c+i;
if (rr>=0 && rc<=7){
if (p[rr][rc] == 1)
return false;
}
}
return true;
}
//显示各个结果
void show(){
for (int i=0; i<8; i++){
for (int j=0; j<8; j++){
printf("%d ", p[i][j]);
}
printf("\n");
}
}
//dfs遍历,参数r为落子的纵座标(行)
void dfs(int r){
if (r == 7){ //若这是最后一行,则在此行中找到可以落最后一个棋子的位置
for (int j=0; j<8; j++){
if (can(r, j)){
p[r][j] = 1; //将该位置设为有棋子
cnt++; //解的个数加一
printf("%d\n", cnt); //输出解的编号
show(); //显示改解
p[r][j] = 0; //回溯,将该位置设为没有棋子
}
}
}else{
for (int j=0; j<8; j++){ //若不是最后一行,则在该行中找到可已落子的位置,再从下一行开始执行dfs()
if (can(r, j)){
p[r][j] = 1; //将该位置设为有棋子
dfs(r+1); //到下一行,调用dfs(r+1)
p[r][j] = 0; //回溯,将该位置设为没有棋子
}
}
}
}
int main()
{
memset(p, 0, sizeof(p));
dfs(0); //从第一行开始搜索
printf("cnt = %d\n", cnt);
return 0;
}