/* * 八皇后问题回溯法编程练习 * 在8×8的棋盘上,放置8个皇后,两个皇后之间不能两两攻击 * 也即,直线,垂直45度、135度方向不能出现两个皇后 * * copyright Michael 2014-12-19 * QQ 1192065414 **/ #include <iostream> #include <stack> #include <stdlib.h> #include <string.h> using namespace std; struct Sposition { int iRow; int iColumn; }; /* * 保存结果使用的栈 **/ stack<Sposition> ResultStack; /* * 判断在水平方向x,垂直方向y,是否可以放置新皇后 **/ bool JudgeIsAcceptable(int x ,int y) { struct Sposition pos; stack<Sposition> resultS(ResultStack); int stackSize = resultS.size(); for ( ; stackSize > 0 ; --stackSize ) { pos = resultS.top(); if( pos.iRow == x ) //判断同一直线上是否已经有皇后 { return false; } if( (x-pos.iRow) == (y-pos.iColumn) ) //判断45度角是否已经有皇后 { return false; } if( (x-pos.iRow) == (pos.iColumn-y) ) //判断-45度角是否已经有皇后 { return false; } resultS.pop(); } return true; } /* * 皇后放置算法 * 0 0 0... * 0 0 0... * 0 0 0... * ...... * 遍历第0列,取第0列的第一个、第二个... * 从第1列开始尝试,然后尝试第2列,当尝试到一列,8行都不能放置皇后,则回溯,返回前一列的下一行继续尝试 **/ void SolveQueue() { Sposition pos; for (int i = 0 ; i < 8 ; ++i ) { //The first line of the queue pos.iRow = i; pos.iColumn = 0; ResultStack.push(pos); int x = 0; //标记当前行,0~7行 int y = 1; //标记当前列,0~7列 while( y<8 ) //从第一列开始 { for ( ; x < 8 ; ++x ) //从第0行开始探索 { if ( JudgeIsAcceptable(x,y) ) { pos.iRow = x; pos.iColumn = y; ResultStack.push(pos); //放置完成,输出结果 if ( 8 == ResultStack.size() ) { while ( !ResultStack.empty() ) { pos = ResultStack.top(); cout<<pos.iRow<<"\t"<<pos.iColumn<<endl; ResultStack.pop(); } } x = 0; //这一列放置完成,继续下一列放置 break; } } if ( 8 == x ) //这一列,8行都不能放置皇后,回溯到上一列的下一行 { pos = ResultStack.top(); x = pos.iRow+1; if ( 8 <= x ) { y = y-2; //如果上一列放置的地方已经是最后一列,则无需继续尝试,应该回溯两列,从前两列继续尝试 ResultStack.pop(); pos = ResultStack.top(); x = pos.iRow+1; } else { --y; //回溯到前一列的下一行继续尝试 } ResultStack.pop(); continue; //控制列数,不进行 ++y 操作 } ++y;; } if ( (8 == y) && (ResultStack.size() != 8) ) //如果8行已经尝试完,但是放置不够8行,出错状态,处理下一种可能性 { while ( !ResultStack.empty() ) { ResultStack.pop(); } } cout<<endl; cout<<endl; } } int main() { SolveQueue(); }
原文地址:http://blog.csdn.net/pray90/article/details/42017385