问题说明:在一个NN的国际象棋盘里摆放n个皇后,使这n个皇后不能互相被对方吃掉。
主题要求:
(1)依次输出成功的各种放置方法。
)最好画棋盘图形,动态地表示试案过程。
)3)程序可以方便地移植到其他标准的板上。
例如,可以放置在44棋盘上的将棋位置{ (0,1 ) (1,3 ) (2,0 ) )、3,2 ) }、{ 0,2 )、0 )、2,3 )、3,1 ) }这两种类型。
主题分析:
一、探索过程分析:
求解NN皇后问题的过程是反求过程。 图-1
(图1-1 )
1、先找第一行的可配置位置,第一行全部可以配置的话,先把第一行女王配置在(0,0 )点。
(图1-2 )
2、再找第二行,第一行(0,0 )已经放皇后了,所以第二行(1,0 )和(1,1 )可以放皇后。 可以放置的是) 1,2 )和) 1,3 )分,) 1,2 )放置皇后。
(图1-3 )
再找第3、3行,找一找,发现没有地方放第3行了,反过来回到第2行说皇后话,从(1、3 )开始找第3行。 如果仍然不行,则返回第一行,将第一行皇后放在下一个可以放置的点上,按顺序类推,在NN以上的所以找到可以放置的位置,在第一行所以位置放置完毕之前输出结果。
4、根据以上规律可知,一个皇后放置在坐标(x,y )时,其下一行位置为(x-1,y ) (x,y ) ) x 1,y )的坐标不能放置皇后。 我们用数组保管本行可以让女王进去的点。 使用循环查找上一行对本职工作的影响,并将受影响的点设置为FAlSE。
5、计算公式为: iplaceover[col-,column-I]=false;
iPlaceOver[col]=false;
iplaceover[col(column-I ) ]=false;
其中col是上一行女王的位置,column是现在的第n行。
6、跌倒过程: for(I=0; i m_iCount; I )
{
如果是可以放if(iplaceover )//皇后的位置
{
m_piSaveQPlace[column]=i; //保存位置
计算queenplace (column 1; //递归搜索下一行
}
) 7、为了动态保存计算结果,程序使用整形后的数组指针来存储每个结果的各行的位置。 为了方便清晰的显示,我使用了结构保存。
8、添加了保存想另存为位图的结果的位图保存函数。
二、程序动态显示试探结果的说明。
为了显示启发式过程,可以将视图指针作为递归函数传递,以便在获得真实结果时更新视图以显示结果。 为了防止显示时过度闪烁,我使用内存直流将位图直接发布到了视图中。
三、班级结构规划:
class CQueen
{
隐私:
结构放置列表
{
int*压力机;
(;
PlaceList * m_pPlaceList;
intm_iListMaxSize;
int m_iListNowSize;
intm_iCount;
CSizem_sizeView;
bool m_bRuning;
int*m_piSaveQPlace; //保存每行皇后的位置
intm_iNowCol;
CBitmap *m_pGridBitmap;
intm_iDrawIndex;
公共:
语音查询(CDC * PDC );
语音下载列表(索引);
voidcomputqueenplace(intcolumn,CView *view=NULL ); //皇后问题求解函数
CSize GetQueenGridSize (;
intgetqueenplace(introw;
int GetListSize (;
int GetDrawIndex (;
语音(introw;
void SaveToBMPFile (;
cqueen(introw );
CQueen (;
~CQueen (;
隐私:
语音下载(CDC * PDC );
语音查询(CDC * PDC );
语音播放器(int * place );
void FreeLi
st();};代码分析:
1、递归代码
void CQueen::ComputQueenPlace(int column , CView *view)
{
int row = 0;
int i ;
int col ;
m_iNowCol = column;
if (column == m_iCount) // 相等说明全部递归完成
{
AddPlace(m_piSaveQPlace);
m_bRuning = false;
return;
}
m_bRuning = true;
int *iPlaceOver = new int[m_iCount];
for ( i = 0 ; i < m_iCount ; i ++)// 初始化为都能放棋子
{
iPlaceOver = true;
}
// 将不能放棋子的点置False
for (i = 0 ; i < column ; i ++)
{
col = m_piSaveQPlace;
if ((col – (column – i)) >= 0)
{
iPlaceOver[col - (column - i)] = false;
}
if ((col + (column – i)) < m_iCount)
{
iPlaceOver[col + (column - i)] = false;
}
iPlaceOver[col] = false;
}
// 递归调用每一次的可能
for (i = 0 ; i < m_iCount ; i ++)
{
if (iPlaceOver)
{
m_piSaveQPlace[column] = i;
if (view != NULL && m_iDrawIndex == -1)
{
CDC *pDC = view->GetDC();
DrawQueenN(pDC);
view->ReleaseDC(pDC);
Sl eep(20);
}
ComputQueenPlace(column + 1 , view);
}
}
m_bRuning = false;
delete[] iPlaceOver;
m_iNowCol = 0;
}2、保存找到的点代码
void CQueen::AddPlace(int *place)
{
if (m_iListNowSize == m_iListMaxSize)
{
m_iListMaxSize += 10;
PlaceList *temlist = new PlaceList[m_iListMaxSize];
for ( int i = 0 ; i < m_iListNowSize; i ++)
{
temlist.Place = m_pPlaceList.Place;
}
delete[] m_pPlaceList;
m_pPlaceList = temlist;
}
int *iPlace = new int[m_iCount];
for ( int i = 0 ; i < m_iCount ; i ++)
{
iPlace = place;
}
m_pPlaceList[m_iListNowSize++].Place = iPlace;
}
用户使用:
(图2-1)
程序运行结果:
(图3-1)
结束语
这段时间有些空,写点数据结构课程设计上面的题目。以后将陆续发点这方面的代码,供大家一起交流,如果代码中有什么不妥当或不构完美的地方,也请大家不吝赐教。