《c和指针》上的一道题,对提示中的回溯算法不太明白,等有时间了好好看看。自己整的一个递归的解,繁琐一点,但是是正解,回头也再优化下。
流程图
代码
<pre name="code" class="cpp">/* CheckNqueens.c */
#include <stdio.h>
#define DIM 8
#define NUM 8
static int array[DIM][DIM]; // 0 --> OK, 1 --> Queen, -1 --> not OK;
static void CopyIntArray(int * t, const int * s, int num); //copy int array from s to t;
static int IsOk(int pos); //is previous queen affected: 1 Not, 0 Yes
static void AddNotOkPos(int pos);
static void PrintArray();
int CheckNqueens(int pos)
{
static int count; // count for solutions
static int numok; // count for queen positions, if == 8, to print chessboard;
int temp[DIM][DIM];
CopyIntArray(&temp[0][0], &array[0][0], DIM*DIM);
while( pos < DIM*DIM ){
int x, y;
x = pos / DIM;
y = pos % DIM;
if(array[x][y] != -1)
if(IsOk(pos)){
array[x][y] = 1;
AddNotOkPos(pos);
if(++ numok == NUM){
PrintArray();
count++;
}else
CheckNqueens(pos+1);
numok--;
CopyIntArray(&array[0][0],&temp[0][0],DIM*DIM);
}
pos++;
}
return count;
}
void CopyIntArray(int * t, const int * s, int num)
{
int i = 0;
while(i++<num)
*t++ = *s++;
}
/* int IsOk(int pos);
while(calculating affected position in array == 1)
return 0;
return 1;
*/
int IsOk(int pos)
{
int x,y,i,j;
x = pos / DIM;
y = pos % DIM;
//horizontal;
i = 0, j = y;
while(i < DIM)
if(array[i++][j]== 1)
return 0;
//vertical;
i = x, j = 0;
while(j < DIM)
if(array[i][j++]== 1)
return 0;
//upper left
i = x, j = y;
while( i >= 0 && j >= 0)
if(array[i--][j--]== 1)
return 0;
//upper right
i = x, j = y;
while( i < DIM && j >= 0)
if(array[i++][j--]== 1)
return 0;
//lower left
i = x, j = y;
while( i >= 0 && j < DIM)
if(array[i--][j++]== 1)
return 0;
//lower right
i = x, j = y;
while( i < DIM && j < DIM)
if(array[i++][j++]== 1)
return 0;
return 1;
}
/* calculting each affected position in array = -1 */
void AddNotOkPos(int pos)
{
int x,y,i,j;
x = pos / DIM;
y = pos % DIM;
//horizontal;
i = 0, j = y;
while(i < DIM)
array[i++][j] = -1;
//vertical;
i = x, j = 0;
while(j < DIM)
array[i][j++] = -1;
//upper left
i = x, j = y;
while( i >= 0 && j >= 0)
array[i--][j--] = -1;
//upper right
i = x, j = y;
while( i < DIM && j >= 0)
array[i++][j--] = -1;
//lower left
i = x, j = y;
while( i >= 0 && j < DIM)
array[i--][j++] = -1;
//lower right
i = x, j = y;
while( i < DIM && j < DIM)
array[i++][j++] = -1;
array[x][y] = 1;
}
//to print the chessboard available
void PrintArray()
{
int i, j;
for(i = 0; i < DIM; i++){
for(j = 0; j < DIM; j++)
if(array[i][j] == 1)
putchar('O');
else
putchar('*');
putchar('\n');
}
putchar('\n');
}