软件设计师算法之回溯法--8皇后问题

    8皇后问题,我想IT人士应该基本都听过了。特别是会下国际象棋的。规则很简单,每一个皇后会攻击每一条线的其它皇后,因此要确保每一条线上(包括直线和对角斜线)只能存在一个皇后。8皇后问题我一直没有编写过代码去实现。今天正好补上。

    如下是实现代码:

#define MAX_ROW    8
#define MAX_COLUMN 8

unsigned char g_QueenArray[MAX_ROW][MAX_COLUMN] = {0};
unsigned int g_QueenSolveCount = 0;

void QueenSolve(int row);

void QueenTest()
{
	QueenSolve(0);
	printf("\r\nTotal count of queen solve = %d\r\n",g_QueenSolveCount);
}

BOOL QueenCheck(int row,int column)
{
	/* 每一行只能有一个皇后,前面解法已保证,不用check*/
	/* 每一列只能有一个皇后 */
	for(int i=0;i<row;i++)
	{
		if(g_QueenArray[i][column])
		{
			return FALSE;
		}
	}
	/* 左上角对角线只能有一个皇后 */
	int i = row-1;
	int j = column-1;
	do 
	{
		//如果超出边界了,那么直接break
		if(i<0 || j<0)
		{
			break;
		}
		if(g_QueenArray[i][j])
		{
			return FALSE;
		}
		i--; 
		j--;
	} while (1);

	/* 右上角对角线只能有一个皇后 */
	i = row-1;
	j = column+1;
	do 
	{
		//如果超出边界了,那么直接break
		if(i<0 || j>=MAX_COLUMN)
		{
			break;
		}
		if(g_QueenArray[i][j])
		{
			return FALSE;
		}
		i--; 
		j++;
	} while (1);

	return TRUE;
}

void PrintQueen()
{
	printf("One of Queen solve result:\r\n");
	for(int i=0;i<MAX_ROW;i++)
	{
		for(int j=0;j<MAX_COLUMN;j++)
		{
			printf("%2d",g_QueenArray[i][j]);
		}
		printf("\r\n");
	}
}

void QueenSolve(int row)
{
	for(int j=0;j<MAX_COLUMN;j++)
	{
		g_QueenArray[row][j] = 1;
		if(QueenCheck(row,j))
		{
			if(MAX_ROW-1 == row)
			{
				PrintQueen();//找到一组解答,之后会继续回溯
				g_QueenSolveCount++;
			}
			else
			{
				QueenSolve(row+1);//前往下一行
			}	
		}
		g_QueenArray[row][j] = 0;//回溯,在下一列放置皇后,尝试可能性
	}
}

     测试运行,输出92种结果。见如下图:

     

    

      但是到这里并没有结束。其实上面的回溯法有关问题,就是效率不高。首先是大量的递归,其次是搜索的空间太大,导致运行的时间会很长。8皇后问题运行的时间一般不会超过1秒(debug版本在我电脑上运行时间为452ms)。但是如果把行和列扩展为12,

          #define MAX_ROW         12   

          #define MAX_COLUMN 12

    计算运行时间:

void QueenTest()
{
	DWORD starTime =GetTickCount();

	QueenSolve(0);
	printf("\r\nTotal count of queen solve = %d\r\n",g_QueenSolveCount);

	DWORD endTime=GetTickCount();
	printf("Running Total time = %d\r\n",endTime-starTime);
}
     12*12皇后问题,debug版本在我的电脑上运行时间为104秒:


         可以看到,运行的时间是巨大的。如果是16*16皇后呢,32*32呢,64*64呢,搜索空间会越来越大导致运行时间不可接受。

         我们有2种办法可以优化,一是把递归修改为迭代实现,二是通过枝减尽快把一些不可能解排除。具体的实现就先遗留在这里。等有空再编写代码实现吧。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值