递归之八皇后问题

八皇后问题简介:

    八皇后是一道很具典型性的题目。它的基本要求是这样的:在一个8*8的矩阵上面放置8个物体,一个矩阵点只允许放置一个物体,任意两个点不能在一行上,也不能在一列上,不能在一条左斜线上,当然也不能在一条右斜线上。

    初看到这道题目,大家的第一印象是遍历,但是经过实践之后发现遍历其实不好写,而且复杂度很低。不仅需要遍历8*8*8*8*8*8*8*8*8 = 2^24次数据,还要判断各种条件,实际的计算复杂度还要比较这个高。其实我们仔细看一看,这中间很多的计算其实很多是不需要的,因为如果我们在某一行没有可以插入的数据的话,那么这后面的行其实就不用考虑了。也就是说,我们只有在保证前面 插入的物体都合法有效的情况下,才能进行下一次的物体插入。无谓的遍历只会是无用功。

   那么,我们应该怎么做呢?其实步骤不太难:

    (1)在第n行寻找可以插入的位置,中间涉及到位置合法性的判断

    (2)如果没有可以插入的位置,返回

    (3)如果有可以插入的位置, 插入数据。此时再判断是否已经是最后一行,如果是,打印输出返回;反之继续对下一行数据进行试探处理。


代码如下:
#include<iostream>
using namespace std;
#define LEN 8

int amount = 0;    // 总共棋盘数

bool IsNoDanger(int row, int k, int(*chess)[LEN])
{
	int i, j;

	// 判断列方向

	for (i=0;i<LEN;i++)
	{
		if (chess[i][k]==1)   // 如果某行的某一列这个位置出现皇后,则处于危险状态,退出
		{
			return false;
		}
	}


	// 判断左上方
	for (i = row, j = k; i >= 0 && j >= 0; i--, j--)
	{
		if (chess[i][j]==1)
		{
			return false;
		}
	}


	//  判断右下方
	for (i=row,j=k;i<LEN&&j<LEN;i++,j++)
	{
		if (chess[i][j]==1)
		{
			return false;
		}
	}

	// 判断右上方

	for (i=row,j=k;i>=0&&j<LEN;i--,j++)
	{
		if (chess[i][j]==1)
		{
			return false;
		}
	}

	// 判断左下方
	for (i=row,j=k;i<LEN&&j>=0;i++,j--)
	{
		if (chess[i][j]==1)
		{
			return false;
		}
	}
	return true;
}


// row 代表起始行    clo 表示列数  (*chess)[LEN]  指向棋盘每一行的指针

void EightQueue(int row,int clo,int (*chess)[LEN])   
{
	int chess2[LEN][LEN];   // 创建临时棋盘存放当前的棋盘
	int i, j;

	// 赋值原棋盘
	for (i=0;i<LEN;i++)
	{
		for (j=0;j<LEN;j++)
		{
			chess2[i][j] = chess[i][j];
		}
	}

	if (row==LEN)       // 如果起始行==LEN,即 row==8 时,打印出棋盘
	{
		amount++;
		cout << "第"<<amount<<"种:"<< endl;

		for(i=0;i<LEN;i++)
		{
			for (j=0;j<LEN;j++)
			{
				cout << chess2[i][j] << "  ";
			}
			cout << endl;
		}
	}
	else
	{
		// 判断这个位置是否有危险,如果有危险,则进行继续往下

		for (j=0;j<clo;j++)    
		{
			if (IsNoDanger(row, j, chess))   // 判断是否有危险
			{
				for (i = 0; i < LEN; i++)
					chess2[row][i] = 0;    // 没有危险,标记为0

				chess2[row][j] = 1;        // 有危险,标记为1
				EightQueue(row + 1, clo, chess2);
			}
		}
	}

}

int main(void)
{
	int chess[LEN][LEN] = { 0 };    // 初始化棋盘为0

	EightQueue(0,LEN, chess);
	return 0;
}

结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八皇后问题是经典的递归问题,可以使用回溯法进行求解。下面是使用C语言实现的递归解决八皇后问题的代码: ```c #include<stdio.h> #include<stdlib.h> #define N 8 int board[N][N]; // 棋盘 void print_board() // 打印棋盘 { int i, j; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%d ", board[i][j]); } printf("\n"); } printf("\n"); } int is_safe(int row, int col) // 判断当前位置是否安全 { int i, j; // 检查行和列 for (i = 0; i < N; i++) { if (board[row][i] || board[i][col]) { return 0; } } // 检查对角线 for (i = row, j = col; i >= 0 && j >= 0; i--, j--) { if (board[i][j]) { return 0; } } for (i = row, j = col; i < N && j >= 0; i++, j--) { if (board[i][j]) { return 0; } } return 1; } int solve(int col) // 递归求解 { if (col == N) { // 找到了一组解 print_board(); return 1; } int i, count = 0; for (i = 0; i < N; i++) { if (is_safe(i, col)) { board[i][col] = 1; count += solve(col + 1); board[i][col] = 0; } } return count; } int main() { int count = solve(0); printf("Total solutions: %d\n", count); return 0; } ``` 上面的代码中,`board`是一个8x8的二维数组,用来表示棋盘。`is_safe`函数用来判断当前位置是否安全,即当前位置是否能放置皇后。`solve`函数是递归求解八皇后问题的核心函数,它从第0列开始,依次尝试在每一行中放置皇后,如果当前位置安全,则将皇后放置在该位置,并递归求解下一列的问题;如果当前位置不安全,则直接返回。当递归到第N列时,表示找到了一组解,输出该解,并返回1。最后在`main`函数中调用`solve`函数,并输出总共找到的解的个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值