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[i]) //如果是可以放皇后的位置 { m_piSaveQPlace[column] = i;//保存位置 ComputQueenPlace(column + 1);//递归搜索下一行 } }7、为了动态保存计算结果,程序使用了一个整形的数组指针存放每次结果中每行的位置。为了方便和清晰的显示,我使用了一个结构保存。
class CQueen { private: struct PlaceList { int *Place; }; PlaceList * m_pPlaceList; int m_iListMaxSize; int m_iListNowSize; int m_iCount; CSize m_sizeView; bool m_bRuning; int *m_piSaveQPlace; // 存每行中皇后的位置 int m_iNowCol; CBitmap *m_pGridBitmap; int m_iDrawIndex; public: void DrawQueenN(CDC *pDC); void DrawList(int index); void ComputQueenPlace(int column , CView *view = NULL); // 皇后问题求解函数 CSize GetQueenGridSize(); int GetQueenPlace(int row); int GetListSize(); int GetDrawIndex(); void SetRow(int row); void SaveToBMPFile(); CQueen(int row); CQueen(); ~CQueen(); private: void DrawGird(CDC *pDC); void DrawQueen(CDC *pDC); void AddPlace(int *place); void FreeList(); };代码分析:
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[i] = true; } // 将不能放棋子的点置False for (i = 0 ; i < column ; i ++) { col = m_piSaveQPlace[i]; 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[i]) { m_piSaveQPlace[column] = i; if (view != NULL && m_iDrawIndex == -1) { CDC *pDC = view->GetDC(); DrawQueenN(pDC); view->ReleaseDC(pDC); Sleep(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[i].Place = m_pPlaceList[i].Place; } delete[] m_pPlaceList; m_pPlaceList = temlist; } int *iPlace = new int[m_iCount]; for ( int i = 0 ; i < m_iCount ; i ++) { iPlace[i] = place[i]; } m_pPlaceList[m_iListNowSize++].Place = iPlace; }
这段时间有些空,写点数据结构课程设计上面的题目。以后将陆续发点这方面的代码,供大家一起交流,如果代码中有什么不妥当或不构完美的地方,也请大家不吝赐教。
PHP实现代码:
<?php /** * 八皇后问题 * * 题目说明: * 在一个N×N的国际象棋棋盘中摆M个皇后,使这M个皇后不能互相被对方吃掉。 * 题目要求: *(1)依次输出各种成功的放置方法。 *(2)最好能画出棋盘的图形形式,并动态的演示试探过程。 *(3)程序能方便的移植到其它规格的棋盘上。 * 例如:在一个4×4的棋盘可以摆放的棋位置{(0,1)(1,3)(2,0)(3,2)},{(0,2)(1,0)(2,3)(3,1)}两种。 */ /** * 函数:解决八皇后问题 * * @param array 二维数组 * @return array 三维数组, 注意:存在重复记录 */ function eight_queen($arr) { $nr = count($arr); $nc = count($arr[0]); $ret_arr = array(); for ($i = 0; $i < $nr; $i++) { for ($j = 0; $j < $nc; $j++) { //放置第一个皇后 $tmp = kill_point($arr, $i, $j); //放置其他皇后 for ($k = 0; $k < $nr; $k++) { for ($l = 0; $l < $nc; $l++) { if ($tmp[$k][$i] == 1 OR $tmp[$k][$l] == 2) { continue; } else { $tmp = kill_point($tmp, $k, $l); } } } $ret_arr[] = $tmp; } } return $ret_arr; } /** * 函数: 输入指定位置的皇后,处理该位置皇后可能吃掉的位置点,修改其值为2(斜, 行, 列). * * @param array 二维数组 * @param int X轴坐标点 * @param int Y轴坐标点 * @param array 二维数组 */ function kill_point($arr, $x = 0, $y = 0) { $n = count($arr); $a = $x; $b = $y; //行 for($i = 0; $i < $n; $i++) { $arr[$x][$i] = 2; } //列 for($i = 0; $i < $n; $i++) { $arr[$i][$y] = 2; } //右下斜 for (;$x < $n AND $y < $n;) { $arr[$x++][$y++] = 2; } //左下斜 for ($x = $a, $y = $b; $x < $n AND $y >= 0;) { $arr[$x++][$y--] = 2; } //右上斜 for ($x = $a, $y = $b; $x >= 0 AND $y < $n;) { $arr[$x--][$y++] = 2; } //左上斜 for ($x = $a, $y = $b; $x >= 0 AND $y >= 0;) { $arr[$x--][$y--] = 2; } //本身位置处理为1 $arr[$a][$b] = 1; return $arr; } /** * 函数: 去除数组重复记录 * * @param array 三维数组 * @return array 去重处理后的三维数组 */ function myarr_unique($arr) { $tmp = array(); foreach($arr as $val) { $tmp[] = serialize($val); } $tmp = array_unique($tmp); unset($arr); foreach($tmp as $val) { $arr[] = unserialize($val); } return $arr; } /** * 函数: 以表格形式输出皇后位置 * * @param array 二维数组 * @param int 单元正方形的宽度值 */ function display($arr, $w = 40) { $nr = count($arr); $nc = count($arr[0]); echo "<table border = '1' style = 'float:left; margin:10px 10px;' width = '".($w*$nr)."'>"; for($i = 0; $i < $nr; $i++) { echo "<tr>"; for($j = 0; $j < $nc; $j++) { if ($arr[$i][$j] == 1 ) { echo "<td width = '".$w."' height = '".$w."' align = 'center'>皇后</td>"; } else if($arr[$i][$j] == 2) { echo "<td width = '".$w."' height = '".$w."'> </td>"; } else { echo "<td width = '".$w."' height = '".$w."'>($i,$j)</td>"; } } echo "</tr>"; } echo "</table>"; } //实例:初始化二维数组 $nr = 4; //行数 $nc = 4; //列数 for($i = 0; $i < $nr; $i++) { for($j = 0; $j < $nc; $j++) { $arr[$i][$j] = 0; } } //八皇后结果输出 $tmp = myarr_unique(eight_queen($arr)); var_dump(count($tmp)); for($i = 0; $i < count($tmp); $i++) { display($tmp[$i]); } /*End of php*/