采用一维数组即可表达全棋盘坐标
n皇后问题,是我对往昔noi生涯的记忆;为了弥补与挽救
宏观规划
1.放置合法性 不受到 列封锁/对角线封锁
列封锁:不能和前面各点的 列 相同(一行一个,行不用看肯定不冲突)
对角线封锁:前点 · 此点 横纵坐标差值的绝对值,不可以相同
(45°即处于对角攻击范围)
两个封锁条件,违反一个,即认为 :此点不可放置
2.打印模块 n*n的遍历,x行y列;在y=a[y](皇后所在列),打印黑块
3.回溯追踪: 从1行到n行,每行都在寻找可放置列
完成放置:A.全部完成?打印! B.部分完成?下一行!(行搜索)a[下列]=0(从头追踪)
放置失败:回退一行,上一行重新放置(列搜索)
全部方案都完成时,会不断遭遇放置失败,直至退回到i=0;从而跳出循环
#include<iostream>
#include<math.h>
#include<stdio.h>
#define N 30
//using namespace std;
int a[N],sum=0;//第几列就是N,里面存的就是第几行 解的总数
//-----------------------打印模块---------------------------
void pr(int n){
printf("第 %d 个 解答:\n",++sum);int x,y;
for(x=1;x<=n;x++){
for(y=1;y<=n;y++){
if(y!=a[x]) printf("□") ;
else printf("■");
}printf("\n");
}
printf("\n");
}
//---------------------放置判断模块----------------------------------
bool place(int t2) {//FT只返回一个
int t1; //遍历·上边的皇后
// A(t1,a[t1]) B(t2,a[t2])
for(t1=1;t1<t2;t1++){
if( (a[t1]==a[t2]) || (abs(a[t1]-a[t2])==abs(t1-t2)) )
return false;
} //同列封锁 斜对角封锁△x=△y
return true;
}//-------------------回溯追踪模块-----------------------------------
void Q(int n) {
int i=1;a[i]=0; //第i行/第i个皇后 列追踪·初始化
while(i>=1) {a[i]++; //下移一列/从头开始 B(i,a[i])
while( a[i]<=n&&!place(i))a[i]++;//找到可放置列
//i行放在a[i]列
if(a[i]<=n) {//安置成功
if(i==n) pr(n); //实现完全部署,打印
else {i++;a[i]=0;}//没有完全部署,向下搜寻,下一列从头开始
}
else i--; //安置失败,回头一行,让上个皇后再走一个
}
//如果完成所有方案确定,将从n回退到0,
}//------------------读入模块-------------------------------------
int main() {int n;
scanf("%d",&n);
Q(n);system("pause");
return 0;
}