八皇后问题

来源:互联网 发布:前列腺高潮经验知乎 编辑:程序博客网 时间:2024/04/28 14:35

最近在学C语言,就用C实现了一遍八皇后问题。
用回溯算法实现的(我学算法学的不系统,不确定正统的回溯算法是不是像我这样实现的)。
写程序用了一个小时,调用了一个小时。整理,重命名变量,写注释又用了一个小时。
很多人用递归实现的,在判断皇后是否冲突时需要每次执行一个循环,影响效率。
我引入了三个一维数组来分别标记指定列,左斜线,右斜线是否放置了皇后。在判断皇后是否冲突时只需要利用下标检查这三个数组就行了。
左斜线,右斜线:我自己引入的概念。
左斜线:棋盘的左上第一条斜线坐标为0,一直到右下角一共有2*n-1条左斜线。
右斜线:左下第一条斜线坐标为0,一直到右上一共有2*n-1条右斜线。


#include <stdio.h>#include <stdlib.h>void solveNQueens();/* * 获取棋盘中指定位置的右斜线索引 * 为方便回溯,需要记录斜线上是否放置了一个皇后 * 对一个指定的n,一共有(n-1)*2 + 1条右斜线 * 假设左下的斜线坐标为0,其相邻的斜线坐标1,依次加1到最右上的斜线坐标为(n-1)*2 */int getRigthDiagonalIndex(int row, int column);/* * 获取棋盘中指定位置的左斜线索引 */int getLeftDiagonalIndex(int row, int column);int resultCount;//结果数//打印结果void printResult();//放置一个皇后void addAQueen(int row, int column);//移除一个皇后void removeAQueen(int row, int column);//找到一行中下一个可以放皇后的位置int findNextValidColumn(int row, int currentColumn);int n;int * result;//暂存一个结果char * columnFlag;//标记:列是否放置了棋盘char * rightDiagonalFlag;//标记:右斜线是否放置了皇后char * leftDiagonalFlag;//标记:左斜线是否放置了皇后int main(void){printf("请输入一个整数\n");scanf("%d", &n);resultCount = 0;solveNQueens();return 0;}//N皇后问题void solveNQueens(){int diagonalCount = n * 2 - 1;//斜线个数result = (int*) malloc(n * sizeof(int));columnFlag = (char*) malloc(n * sizeof(char));rightDiagonalFlag = (char*) malloc(diagonalCount * sizeof(char));leftDiagonalFlag = (char*) malloc(diagonalCount * sizeof(char));int row,column,rightDiagonal,leftDiagonal,i;//initfor ( i = 0; i < n; i++){columnFlag[i] = '0';}for ( i = 0; i < diagonalCount; i++){rightDiagonalFlag[i] = '0';leftDiagonalFlag[i] = '0';}/* * 回溯算法 */row = 0;result[0] = -1;while ( row >= 0 ){  if ( result[row] >= 0 ) //如果当前行原来放置了一个皇后,先移除  {  removeAQueen(row, result[row]);  }    //找到下一个可以放置皇后的位置      column = findNextValidColumn(row, result[row]);            if ( column == -1 ) //该行找不到可以放皇后的位置了      {      --row;//返回上一行  }  else  {  result[row] = column;//记录皇后位置  addAQueen(row, column);//标记该皇后所在的列和斜线  ++row;//到下一行    if ( row == n )//找到一个解  {   printResult(result, n); --row;//退回到上一行  }  else//初始化下一行  {  result[row] = -1;  }  }}}void addAQueen(int row, int column){int rightDiagonal = getRigthDiagonalIndex(row, column);int leftDiagonal = getLeftDiagonalIndex(row, column);columnFlag[column] = '1';rightDiagonalFlag[rightDiagonal] = '1';leftDiagonalFlag[leftDiagonal] = '1';}int findNextValidColumn(int row, int currentColumn){ int column; int rightDiagonal; int leftDiagonal; for( column = currentColumn + 1; column < n; column++) {    rightDiagonal = getRigthDiagonalIndex(row, column);leftDiagonal = getLeftDiagonalIndex(row, column);if ( columnFlag[column] == '0' && rightDiagonalFlag[rightDiagonal] == '0'  && leftDiagonalFlag[leftDiagonal] == '0' ){ return column;} } return -1;}   void removeAQueen(int row, int column){columnFlag[column] = '0';int rightDiagonal = getRigthDiagonalIndex(row, column);rightDiagonalFlag[rightDiagonal] = '0';int leftDiagonal = getLeftDiagonalIndex(row, column);leftDiagonalFlag[leftDiagonal] = '0';}int getRigthDiagonalIndex(int row, int column){return (n - 1) + column - row;}int getLeftDiagonalIndex(int row, int column){return row + column;}void printResult(){printf("第%d个解:\n", ++resultCount);int i,j,k;for (i = 0; i < n; i++){for (j = 0; j < *(result + i); j++){printf("%c ", '*');}printf("%c ", 'Q');for (k = *(result + i) + 1; k < n; k++){printf("%c ", '*');}printf("%c",'\n');}printf("%c",'\n');}


0 0
原创粉丝点击