实现八皇后问题的方法,是数据结构与算法中非常经典的一个算法。
一般在八皇后问题中,我们要求解的是一个8*8的国际象棋棋盘中,放下8个皇后且互相不能攻击的排列总数。皇后的攻击范围为整行,整列,以及其斜对角线。
由于皇后的攻击范围特性,注定我们每行只能放下一个皇后,于是我们要做的只是逐行放下皇后。八皇后问题是回溯法的典型问题。这里我们用的方法很简单:
从第一行开始逐个检索安全位置摆放皇后,一旦有安全位置则考虑下一行的安全位置。如果发现某行没有安全位置,则返回上一行继续检索安全位置;如果发现在最后一行找到了安全位置则输出整个棋盘。
代码如下:
%%八皇后问题 :在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。
eitht_queen()->
spawn(fun() -> queen_pos_y(0) end),
ok.
queen_pos_y(DY)->
QueenList = get_queen(),
lists:foreach(fun(DX)->
case is_safe(DX,DY,QueenList) of
true->
QueenListNew = [{DX,DY}|QueenList],
set_queen(QueenListNew),
if DY < 7 ->
queen_pos_y(DY+1);
true->
io:format("printf ~p ~n",[{"count :",get_count(),"queen pos list :",QueenListNew}])
end;
_->
nil
end
end,lists:seq(0,7)).
get_queen()->
case get(queen) of
undefined->
[];
L->
L
end.
set_queen(QL)->
put(queen,QL).
get_count()->
case get(count) of
undefined->
put(count,1),
1;
C->
put(count,C+1),
C+1
end.
is_safe(_,_,[])->
true;
is_safe(DX,DY,QueenList)->
try
lists:foreach(fun(TTY)->
{TTX,_} = lists:keyfind(TTY,2,QueenList),
if TTX == DX ->
throw(false);
TTY == DY->
throw(false);
TTX - TTY == DX - DY orelse TTX + TTY == DX + DY ->
throw(false);
true->
nil
end
end,lists:seq(0,DY-1)),
true
catch
_:_->
false
end.