算法学习:八皇后问题(回溯算法)

国际象棋中,皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(8*8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
已知8皇后问题一共有92组解,即92个不同的皇后串

回溯法:也叫“试探法”。解决问题的时候,没进行一步,都是抱着试一试的态度,如果发现当前的选择达不到目的或者并不是最优的,则立刻做出退出操作。

回溯法和递归:
递归:你非常明确要做什么(每一步该怎么走你都非常明白)
回溯:有点类似于穷举法,将所有的情况都尝试一遍,如果行就继续往下走,如果不行就倒回到上一步。回溯法在实现的时候可以用递归

思路:1、从第0行开始,在第0行的第0列放置一个皇后,依次在第1行~第7行的某个位置放置一个皇后,判断该位置能否放置皇后,如果不行,则在该位置后面一个位置再尝试着放一个皇后,如果可以则放一个皇后在这个位置,再在下一行尝试,如果该行所有的位置都不行,则回溯到上一行,改变上一行的皇后的位置,继续往下尝试
2、如果尝试到了最后一行,并且最后一行有位置能够摆放皇后,则说明我们的目的达到了。
3、如果此次尝试成功则用同样的方法继续尝试其他不同的摆法。

//两个全局变量
int board[8][8] = {0};	//棋盘
int sum = 0;		//计数器

//如果可以摆放皇后则返回 1,否则返回 0
int check(int row, int col)	//判断(row, col)位置是否可以摆放皇后
{
	int i, j;
	//判断第col列有没有皇后
	for(i = 0; i < 8; i++)
	{
		if( 1 == board[i][col] )
			return 0;
	}
	//判断左上对角线有没有皇后
	for(i = row, j = col; i >= 0 && j >= 0; i--, j--)
	{
		if( 1 == board[i][j] )
			return 0;
	}
	//判断右上对角线有没有皇后
	for(i = row, j = col; i >= 0 && j < 8; i--, j++)
	{
		if( 1 == board[i][j] )
			return 0;
	}
	return 1;
}
//放皇后
void put_queen(int row)
{
	if(8 == row)	//递归结束条件
	{
		sum++;	//找到一种解法,计数器++
		return;
	}
	int i;
	for(i = 0; i < 8; i++)
	{
		if( check(row, i) )
		{
			board[row][i] = 1;	//放下皇后
			put_queen(row + 1);	//递归
			board[row][i] = 0;	//回溯前把之前的皇后标记清零
		}
	}
}

int main(void)
{	
	put_queen(0);	//从第0行开始放皇后
	printf("总共有 %d 种摆法\n", sum);		//总共有92种摆法
	
	return 0;
}
发布了50 篇原创文章 · 获赞 5 · 访问量 1532

猜你喜欢

转载自blog.csdn.net/qq_42483691/article/details/104580545
今日推荐