八皇后问题是一个比较经典的问题。
问题如百度百科上
网上递归版本的八皇后解法很多。非递归版本相对较少。
事实上,递归版本和非递归版本原理类似。非递归版本借用栈来实现深度搜索,根据栈的元素个数来确定是否回溯的。
先贴代码~(C++ 运行环境 dev C++ 5.11 win10 )
#include <stdio.h>
#include <memory.h>
//http://paste.ubuntu.com/23583833/
typedef struct myStack{
int a[100];
int top;
}myStack;
void init(myStack *s){
s->top = -1;
}
bool isempty(myStack *s){
return s->top==-1;
}
int size(myStack *s){
return s->top+1;
}
void pop(myStack *s){
if(!isempty(s))
s->top--;
}
void push(myStack *s,int data){
s->a[++s->top] = data;
}
int get(myStack *s,int index){
return s->a[index];
}
int top(myStack *s){
return s->a[s->top];
}
bool crash(myStack *s, int data){
if(isempty(s))
return false;
int ssize = size(s);
int state = -1;
for(int i = 0; i < size(s); ++i){
state = get(s,i);
if(data==state || (ssize-i==data-state || ssize-i==state-data)){
return true;
}
}
return false;
}
int main(){
myStack *s = (myStack*)malloc(sizeof(myStack));
init(s);
int count = 0;
int i = 0;
while(i<8 || !isempty(s)){
// note :if语句顺序不能乱。
if(size(s) == 8){
// 找到结果 ,打印输出
for(int p=0; p<8; ++p)
printf("%d ",get(s,p));
printf("\n");
// 结果总数 +1
count++;
pop(s);
i = top(s) + 1;//下一个待找的位置
pop(s);
//如果当前的位置正确,那么该行不会出现其他位置满足条件了,所以pop两次。
}else if(i==8){
// 判断是否超过棋盘范围
i = top(s) + 1;
pop(s);
} else if(crash(s,i)){
//如果冲突,那么就去找下一个位置
++i;
} else {
//压栈 ,dfs
push(s,i);
i = 0;
}
}
printf("共计%d种可能!",count);
free(s);
return 0;
}
首先定义了myStack栈结构,其中top为栈顶标记。后面定义了栈的基本操作,如判栈空,取栈顶元素,取第i个元素(i从0开始),栈元素个数,压栈,出栈等。
crash判断当前位置是否与之前冲突。
判断条件
(ssize-i==data-state || ssize-i==state-data)
判断了斜线攻击的情况。
主函数里面提供了深度优先搜索的方法。其中需要注意的是,if条件顺序不能颠倒,否则可能找不到while循环的出口,导致死循环。(捂脸,第一次运行的时候i==8和crash(s,i)顺序颠倒了,导致i一直往上加而程序不能终止)
程序运行截图: