〖问题描述〗
在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相冲突(在每一横列竖列斜列只有一个皇后)。
这里我是用回溯法来实现的,存储方式采用的是孩子兄弟表示法。即将一般的数改用二叉树的形式来存储,左子树指向第一个孩子节点,右子树指向第一个兄弟节点。
因为用递归思路比较简单,我就直接帖代码了。
QueenTree是整个树的类,Node是每个节点的类。
class QueenTree
{
public :
QueenTree();
void Build();
void Display();
private :
class Node
{
public :
Node();
Node(Node * );
bool IsValid( int );
void Print();
private :
friend class QueenTree;
int chesses[ 8 ];
bool valid;
Node * child;
Node * sibling;
int rowindex;
} * head;
private :
void _Build(Node *& , int , int ,Node * );
void _Display(Node * );
};
其中chesses[i]=j 是指第i个棋子放在第i 行第j 列,valid用于说明改节点是否满足条件,rowindex为了输出方便加入的,说明这个节点已放置了几行棋子。
#include < iostream >
#include " QueenTree.h "
QueenTree::QueenTree()
{
head = new Node;
}
QueenTree::Node::Node()
{
for ( int i = 0 ;i < 8 ;i ++ )
chesses[i] =- 1 ;
valid = true ;
child = NULL;
sibling = NULL;
rowindex =- 1 ;
}
bool QueenTree::Node::IsValid( int r)
{
for ( int i = 0 ;i < r;i ++ )
{
if (chesses[i] == chesses[r])
{
valid = false ;
return false ;
}
if ((i - chesses[i]) == (r - chesses[r]))
{
valid = false ;
return false ;
}
if ((i + chesses[i]) == (r + chesses[r]))
{
valid = false ;
return false ;
}
}
valid = true ;
return true ;
}
void QueenTree::Build()
{
_Build(head, - 1 , - 1 ,NULL);
}
void QueenTree::_Build(Node * & t, int r, int c,Node * father)
{
if (t == head)
{
_Build(t -> child,r + 1 ,c + 1 ,t);
}
else
{
t = new Node(father);
t -> chesses[r] = c;
if (r < 7 )
{
if (t -> IsValid(r))
_Build(t -> child,r + 1 , 0 ,t);
else
t -> child = NULL;
}
else
{
t -> IsValid(r);
t -> child = NULL;
}
if (c < 7 )
_Build(t -> sibling,r,c + 1 ,father);
else
t -> sibling = NULL;
}
}
QueenTree::Node::Node(Node * father)
{
bool flag = false ;
for ( int i = 0 ;i < 8 ;i ++ )
{
if (father -> chesses[i] ==- 1 &&! flag)
{
rowindex = i;
flag = true ;
}
chesses[i] = father -> chesses[i];
}
valid = true ;
child = NULL;
sibling = NULL;
}
void QueenTree::Display()
{
_Display(head);
}
void QueenTree::_Display(Node * t)
{
if (t -> rowindex == 7 && t -> valid)
t -> Print();
if (t -> child)
_Display(t -> child);
if (t -> sibling)
_Display(t -> sibling);
}
void QueenTree::Node::Print()
{
static int count = 0 ;
std::cout << " No. " << count ++<< " : " ;
for ( int i = 0 ;i < 8 ;i ++ )
std::cout << " ( " << i << " , " << chesses[i] << " ) " ;
std::cout << std::endl;
}
Node有两个构造函数,一个用于建立根节点,一个是建立其余节点,因为非根节点要将它双亲节点的棋子放置拷贝到自己里面,所以加了一个father指针。
#include " QueenTree.h "
int main()
{
QueenTree * t = new QueenTree;
t -> Build();
t -> Display();
}
八皇后问题共有92组解,也在下面:( i , j ) 表示棋子放在i 行j 列
No.0: (0,0) (1,4) (2,7) (3,5) (4,2) (5,6) (6,1) (7,3)
No.1: (0,0) (1,5) (2,7) (3,2) (4,6) (5,3) (6,1) (7,4)
No.2: (0,0) (1,6) (2,3) (3,5) (4,7) (5,1) (6,4) (7,2)
No.3: (0,0) (1,6) (2,4) (3,7) (4,1) (5,3) (6,5) (7,2)
No.4: (0,1) (1,3) (2,5) (3,7) (4,2) (5,0) (6,6) (7,4)
No.5: (0,1) (1,4) (2,6) (3,0) (4,2) (5,7) (6,5) (7,3)
No.6: (0,1) (1,4) (2,6) (3,3) (4,0) (5,7) (6,5) (7,2)
No.7: (0,1) (1,5) (2,0) (3,6) (4,3) (5,7) (6,2) (7,4)
No.8: (0,1) (1,5) (2,7) (3,2) (4,0) (5,3) (6,6) (7,4)
No.9: (0,1) (1,6) (2,2) (3,5) (4,7) (5,4) (6,0) (7,3)
No.10: (0,1) (1,6) (2,4) (3,7) (4,0) (5,3) (6,5) (7,2)
No.11: (0,1) (1,7) (2,5) (3,0) (4,2) (5,4) (6,6) (7,3)
No.12: (0,2) (1,0) (2,6) (3,4) (4,7) (5,1) (6,3) (7,5)
No.13: (0,2) (1,4) (2,1) (3,7) (4,0) (5,6) (6,3) (7,5)
No.14: (0,2) (1,4) (2,1) (3,7) (4,5) (5,3) (6,6) (7,0)
No.15: (0,2) (1,4) (2,6) (3,0) (4,3) (5,1) (6,7) (7,5)
No.16: (0,2) (1,4) (2,7) (3,3) (4,0) (5,6) (6,1) (7,5)
No.17: (0,2) (1,5) (2,1) (3,4) (4,7) (5,0) (6,6) (7,3)
No.18: (0,2) (1,5) (2,1) (3,6) (4,0) (5,3) (6,7) (7,4)
No.19: (0,2) (1,5) (2,1) (3,6) (4,4) (5,0) (6,7) (7,3)
No.20: (0,2) (1,5) (2,3) (3,0) (4,7) (5,4) (6,6) (7,1)
No.21: (0,2) (1,5) (2,3) (3,1) (4,7) (5,4) (6,6) (7,0)
No.22: (0,2) (1,5) (2,7) (3,0) (4,3) (5,6) (6,4) (7,1)
No.23: (0,2) (1,5) (2,7) (3,0) (4,4) (5,6) (6,1) (7,3)
No.24: (0,2) (1,5) (2,7) (3,1) (4,3) (5,0) (6,6) (7,4)
No.25: (0,2) (1,6) (2,1) (3,7) (4,4) (5,0) (6,3) (7,5)
No.26: (0,2) (1,6) (2,1) (3,7) (4,5) (5,3) (6,0) (7,4)
No.27: (0,2) (1,7) (2,3) (3,6) (4,0) (5,5) (6,1) (7,4)
No.28: (0,3) (1,0) (2,4) (3,7) (4,1) (5,6) (6,2) (7,5)
No.29: (0,3) (1,0) (2,4) (3,7) (4,5) (5,2) (6,6) (7,1)
No.30: (0,3) (1,1) (2,4) (3,7) (4,5) (5,0) (6,2) (7,6)
No.31: (0,3) (1,1) (2,6) (3,2) (4,5) (5,7) (6,0) (7,4)
No.32: (0,3) (1,1) (2,6) (3,2) (4,5) (5,7) (6,4) (7,0)
No.33: (0,3) (1,1) (2,6) (3,4) (4,0) (5,7) (6,5) (7,2)
No.34: (0,3) (1,1) (2,7) (3,4) (4,6) (5,0) (6,2) (7,5)
No.35: (0,3) (1,1) (2,7) (3,5) (4,0) (5,2) (6,4) (7,6)
No.36: (0,3) (1,5) (2,0) (3,4) (4,1) (5,7) (6,2) (7,6)
No.37: (0,3) (1,5) (2,7) (3,1) (4,6) (5,0) (6,2) (7,4)
No.38: (0,3) (1,5) (2,7) (3,2) (4,0) (5,6) (6,4) (7,1)
No.39: (0,3) (1,6) (2,0) (3,7) (4,4) (5,1) (6,5) (7,2)
No.40: (0,3) (1,6) (2,2) (3,7) (4,1) (5,4) (6,0) (7,5)
No.41: (0,3) (1,6) (2,4) (3,1) (4,5) (5,0) (6,2) (7,7)
No.42: (0,3) (1,6) (2,4) (3,2) (4,0) (5,5) (6,7) (7,1)
No.43: (0,3) (1,7) (2,0) (3,2) (4,5) (5,1) (6,6) (7,4)
No.44: (0,3) (1,7) (2,0) (3,4) (4,6) (5,1) (6,5) (7,2)
No.45: (0,3) (1,7) (2,4) (3,2) (4,0) (5,6) (6,1) (7,5)
No.46: (0,4) (1,0) (2,3) (3,5) (4,7) (5,1) (6,6) (7,2)
No.47: (0,4) (1,0) (2,7) (3,3) (4,1) (5,6) (6,2) (7,5)
No.48: (0,4) (1,0) (2,7) (3,5) (4,2) (5,6) (6,1) (7,3)
No.49: (0,4) (1,1) (2,3) (3,5) (4,7) (5,2) (6,0) (7,6)
No.50: (0,4) (1,1) (2,3) (3,6) (4,2) (5,7) (6,5) (7,0)
No.51: (0,4) (1,1) (2,5) (3,0) (4,6) (5,3) (6,7) (7,2)
No.52: (0,4) (1,1) (2,7) (3,0) (4,3) (5,6) (6,2) (7,5)
No.53: (0,4) (1,2) (2,0) (3,5) (4,7) (5,1) (6,3) (7,6)
No.54: (0,4) (1,2) (2,0) (3,6) (4,1) (5,7) (6,5) (7,3)
No.55: (0,4) (1,2) (2,7) (3,3) (4,6) (5,0) (6,5) (7,1)
No.56: (0,4) (1,6) (2,0) (3,2) (4,7) (5,5) (6,3) (7,1)
No.57: (0,4) (1,6) (2,0) (3,3) (4,1) (5,7) (6,5) (7,2)
No.58: (0,4) (1,6) (2,1) (3,3) (4,7) (5,0) (6,2) (7,5)
No.59: (0,4) (1,6) (2,1) (3,5) (4,2) (5,0) (6,3) (7,7)
No.60: (0,4) (1,6) (2,1) (3,5) (4,2) (5,0) (6,7) (7,3)
No.61: (0,4) (1,6) (2,3) (3,0) (4,2) (5,7) (6,5) (7,1)
No.62: (0,4) (1,7) (2,3) (3,0) (4,2) (5,5) (6,1) (7,6)
No.63: (0,4) (1,7) (2,3) (3,0) (4,6) (5,1) (6,5) (7,2)
No.64: (0,5) (1,0) (2,4) (3,1) (4,7) (5,2) (6,6) (7,3)
No.65: (0,5) (1,1) (2,6) (3,0) (4,2) (5,4) (6,7) (7,3)
No.66: (0,5) (1,1) (2,6) (3,0) (4,3) (5,7) (6,4) (7,2)
No.67: (0,5) (1,2) (2,0) (3,6) (4,4) (5,7) (6,1) (7,3)
No.68: (0,5) (1,2) (2,0) (3,7) (4,3) (5,1) (6,6) (7,4)
No.69: (0,5) (1,2) (2,0) (3,7) (4,4) (5,1) (6,3) (7,6)
No.70: (0,5) (1,2) (2,4) (3,6) (4,0) (5,3) (6,1) (7,7)
No.71: (0,5) (1,2) (2,4) (3,7) (4,0) (5,3) (6,1) (7,6)
No.72: (0,5) (1,2) (2,6) (3,1) (4,3) (5,7) (6,0) (7,4)
No.73: (0,5) (1,2) (2,6) (3,1) (4,7) (5,4) (6,0) (7,3)
No.74: (0,5) (1,2) (2,6) (3,3) (4,0) (5,7) (6,1) (7,4)
No.75: (0,5) (1,3) (2,0) (3,4) (4,7) (5,1) (6,6) (7,2)
No.76: (0,5) (1,3) (2,1) (3,7) (4,4) (5,6) (6,0) (7,2)
No.77: (0,5) (1,3) (2,6) (3,0) (4,2) (5,4) (6,1) (7,7)
No.78: (0,5) (1,3) (2,6) (3,0) (4,7) (5,1) (6,4) (7,2)
No.79: (0,5) (1,7) (2,1) (3,3) (4,0) (5,6) (6,4) (7,2)
No.80: (0,6) (1,0) (2,2) (3,7) (4,5) (5,3) (6,1) (7,4)
No.81: (0,6) (1,1) (2,3) (3,0) (4,7) (5,4) (6,2) (7,5)
No.82: (0,6) (1,1) (2,5) (3,2) (4,0) (5,3) (6,7) (7,4)
No.83: (0,6) (1,2) (2,0) (3,5) (4,7) (5,4) (6,1) (7,3)
No.84: (0,6) (1,2) (2,7) (3,1) (4,4) (5,0) (6,5) (7,3)
No.85: (0,6) (1,3) (2,1) (3,4) (4,7) (5,0) (6,2) (7,5)
No.86: (0,6) (1,3) (2,1) (3,7) (4,5) (5,0) (6,2) (7,4)
No.87: (0,6) (1,4) (2,2) (3,0) (4,5) (5,7) (6,1) (7,3)
No.88: (0,7) (1,1) (2,3) (3,0) (4,6) (5,4) (6,2) (7,5)
No.89: (0,7) (1,1) (2,4) (3,2) (4,0) (5,6) (6,3) (7,5)
No.90: (0,7) (1,2) (2,0) (3,5) (4,1) (5,4) (6,6) (7,3)
No.91: (0,7) (1,3) (2,0) (3,2) (4,5) (5,1) (6,6) (7,4)
最后再说一点,这里我是用树的前序遍历来实现回溯的,也可以用栈来模拟。对于这道题也可以用循环来实现。