回溯问题:八皇后

问题介绍:

    在国际下象棋中,皇后可以在横、竖、斜线上不限步数吃掉其他棋子,故需要考虑怎么将8个皇后放在棋盘上(棋盘为8x8)。此为八皇后问题,为经典回溯算法问题,以下输出结果将输出‘*’为为方棋子的空位,‘@’为放置的皇后位置:
static char Queen[8][8];
static int a[8];   //a数组代表列冲突
static int b[15];  //b数组代表主对角线冲突
static int c[15];  //c数组代表从对角线冲突
static int iQueenNum = 0;  //记录总的棋盘状态数

void Cal(int i);  //i代表行数

int main()
{
	int iLine,iColumn;

	//棋盘初始化,空格为*,放置皇后的地方为@
	for(iLine=0;iLine<8;iLine++)
	{
		a[iLine] = 0;  //列标记初始化为0,表示无列冲突
		for(iColumn=0;iColumn<8;iColumn++)
			Queen[iLine][iColumn] = '*';
	}

	//主、从对角线标记初始化为0,表示没有冲突
	for(iLine=0;iLine<15;iLine++) 
		b[iLine]=c[iLine]=0;
	Cal(0);
	return 0;
} 

void Cal(int i)
{
	int iColumn;
	for (iColumn=0;iColumn<8;iColumn++)
	{
		if(a[iColumn]==0&&b[i-iColumn+7]==0&&c[iColumn+i]==0)
			//如果没有冲突存在
		{
			Queen[i][iColumn] = '@';  //放皇后
			a[iColumn] = 1;           //下一次该列上不能放皇后
			b[i-iColumn+7] = 1;       //下一次该主对角线上不能放皇后
			c[iColumn+i] = 1;         //下一次该从对角线上不能放皇后
			if(i<7) Cal(i+1);         //如果行还没有遍历完,进入下一行
			else  //否则输出
			{
				//输出棋盘状态
				int iLine,iColumn;
				printf("第%d种状态为:\n",++iQueenNum);
			for(iLine=0;iLine<8;iLine++)
			{
				for(iColumn=0;iColumn<8;iColumn++)
					printf("%c",Queen[iLine][iColumn]);
				printf("\n");
			}
			printf("\n\n");
			}

			//如果前次的皇后导致后面放置无论如何都不能满足要求,则回溯,重置
			Queen[i][iColumn] = '*';
			a[iColumn] = 0;
			b[i-iColumn+7] = 0;
			c[iColumn+i] = 0;
		}
	}
}

输出结果为:
回溯问题:八皇后_第1张图片

共92种解法,即92种不同排放方法。

你可能感兴趣的:(经典算法)