软件设计师算法之回溯法--8皇后问题
2017-09-16 13:34
423 查看
8皇后问题,我想IT人士应该基本都听过了。特别是会下国际象棋的。规则很简单,每一个皇后会攻击每一条线的其它皇后,因此要确保每一条线上(包括直线和对角斜线)只能存在一个皇后。8皇后问题我一直没有编写过代码去实现。今天正好补上。
如下是实现代码:
测试运行,输出92种结果。见如下图:
![](http://img.blog.csdn.net/20170916115117932)
但是到这里并没有结束。其实上面的回溯法有关问题,就是效率不高。首先是大量的递归,其次是搜索的空间太大,导致运行的时间会很长。8皇后问题运行的时间一般不会超过1秒(debug版本在我电脑上运行时间为452ms)。但是如果把行和列扩展为12,
#define MAX_ROW 12
#define MAX_COLUMN 12
计算运行时间:
![](http://img.blog.csdn.net/20170916132905307)
可以看到,运行的时间是巨大的。如果是16*16皇后呢,32*32呢,64*64呢,搜索空间会越来越大导致运行时间不可接受。
我们有2种办法可以优化,一是把递归修改为迭代实现,二是通过枝减尽快把一些不可能解排除。具体的实现就先遗留在这里。等有空再编写代码实现吧。
如下是实现代码:
#define MAX_ROW 8 #define MAX_COLUMN 8 unsigned char g_QueenArray[MAX_ROW][MAX_COLUMN] = {0}; unsigned int g_QueenSolveCount = 0; void QueenSolve(int row); void QueenTest() { QueenSolve(0); printf("\r\nTotal count of queen solve = %d\r\n",g_QueenSolveCount); } BOOL QueenCheck(int row,int column) { /* 每一行只能有一个皇后,前面解法已保证,不用check*/ /* 每一列只能有一个皇后 */ for(int i=0;i<row;i++) { if(g_QueenArray[i][column]) { return FALSE; } } /* 左上角对角线只能有一个皇后 */ int i = row-1; int j = column-1; do { //如果超出边界了,那么直接break if(i<0 || j<0) { break; } if(g_QueenArray[i][j]) { return FALSE; } i--; j--; } while (1); /* 右上角对角线只能有一个皇后 */ i = row-1; j = column+1; do { //如果超出边界了,那么直接break if(i<0 || j>=MAX_COLUMN) { break; } if(g_QueenArray[i][j]) { return FALSE; } i--; j++; } while (1); return TRUE; } void PrintQueen() { printf("One of Queen solve result:\r\n"); for(int i=0;i<MAX_ROW;i++) { for(int j=0;j<MAX_COLUMN;j++) { printf("%2d",g_QueenArray[i][j]); } printf("\r\n"); } } void QueenSolve(int row) { for(int j=0;j<MAX_COLUMN;j++) { g_QueenArray[row][j] = 1; if(QueenCheck(row,j)) { if(MAX_ROW-1 == row) { PrintQueen();//找到一组解答,之后会继续回溯 g_QueenSolveCount++; } else { QueenSolve(row+1);//前往下一行 } } g_QueenArray[row][j] = 0;//回溯,在下一列放置皇后,尝试可能性 } }
测试运行,输出92种结果。见如下图:
但是到这里并没有结束。其实上面的回溯法有关问题,就是效率不高。首先是大量的递归,其次是搜索的空间太大,导致运行的时间会很长。8皇后问题运行的时间一般不会超过1秒(debug版本在我电脑上运行时间为452ms)。但是如果把行和列扩展为12,
#define MAX_ROW 12
#define MAX_COLUMN 12
计算运行时间:
void QueenTest() { DWORD starTime =GetTickCount(); QueenSolve(0); printf("\r\nTotal count of queen solve = %d\r\n",g_QueenSolveCount); DWORD endTime=GetTickCount(); printf("Running Total time = %d\r\n",endTime-starTime); }12*12皇后问题,debug版本在我的电脑上运行时间为104秒:
可以看到,运行的时间是巨大的。如果是16*16皇后呢,32*32呢,64*64呢,搜索空间会越来越大导致运行时间不可接受。
我们有2种办法可以优化,一是把递归修改为迭代实现,二是通过枝减尽快把一些不可能解排除。具体的实现就先遗留在这里。等有空再编写代码实现吧。
相关文章推荐
- 国际象棋“皇后”问题的回溯算法
- 回溯算法 8皇后问题的一种解法 适合初学者观察整个回溯的过程
- 回溯算法—N皇后问题
- 回溯算法-8皇后问题
- 回溯算法之N皇后问题的求解
- 回溯算法之n皇后问题
- 算法学习:回溯解决4皇后问题
- 国际象棋“皇后”问题的回溯算法
- 回溯经典算法之四皇后问题
- 【算法分析】回溯法解八皇后问题(n皇后问题)
- 回溯(su)算法之N皇后问题
- 算法分析与设计回溯法之n皇后问题
- 国际象棋“皇后”问题的回溯算法
- 八皇后问题算法(回溯与递归算法)
- 国际象棋“皇后”问题的回溯算法
- 回溯算法n皇后问题
- 求 N 皇后问题回溯算法
- 回溯算法之N皇后问题
- 国际象棋“皇后”问题的回溯算法
- 国际象棋“皇后”问题的回溯算法