回溯法解决N皇后问题——递归与非递归求解

回溯法其实也是一种搜索算法,它可以方便的搜索解空间。 

回溯法解题通常可以从以下三步入手: 

1、针对问题,定义解空间 

2、确定易于搜索的解空间结构 

3、以深度优先的方式搜索解空间,并在搜索的过程中进行剪枝 

回溯法通常在解空间树上进行搜索,而解空间树通常有子集树和排列树。 

针对这两个问题,算法的框架基本如下: 

用回溯法搜索子集合树的一般框架

void backtrack(int t){
  if(t > n) output(x);
  else{
    for(int i = f(n,t); i <= g(n,t);i++){
          x[t] = h(i);
          if(constraint(t) && bound(t)) backtrack(t+1);
     }
  }
}

网上看到些非递归解法,需要申请了些额外空间,我这里没有另外开辟空间,仅供参考,如果有问题,请留言。

不过我这里没考虑算法效率,网上有用公式求解,还有利用位操作进行计算的,有兴趣的可以关注下。

#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
void Queen_n(int n);
int main()
{
	int n;//N皇后
	scanf("%d",&n);
	Queen_n(n);
	return 0;
}
bool place(int *x,int col,int n)
{
	for(int i=0;i<col;i++)
	{
		if( x[col] == x[i] || abs(i-col) == abs(x[col]-x[i]) )
			return false;
	}
	return true;
}
void BackTracing(int *x,int &sum,int t,int n)
{
	if( t > n-1 )
	{
		sum ++;
		printf("Column\tRow\n");
		for(int i=0;i<n;i++)
			printf("%3d\t%d\n",i,x[i]);
	}
	else
	{
		for(int j=0;j<n;j++)
		{
			x[t] = j;
			if( place(x,t,n) )
			{
				BackTracing(x,sum,t+1,n);
			}
		}
	}
}
void Back_not_resur(int *x,int &sum,int n)//非递归解法
{
	int i=0,j=0;
	x[i] = -1;	//初始化为-1
	while( i<n && i>=0)
	{
		x[i] += 1;
		while(j<n)	//如果不能放置,则该列上,继续放在下一行
		{
			x[i] = j;
			if( !place(x,i,n) )
				j++;
			else break;
		}
		if( j<n)
		{
			if(i == n-1)	//i=n-1,即求解到最后一列,即求解完成
			{
				sum++;
				printf("Column\tRow\n");
				for(int k=0;k<n;k++)
					printf("%3d\t%d\n",k,x[k]);
				j++;	//继续求解下一个解
				//break;	//只求一个解,即结束

			}
			else	//求解下一列,下一列从第0行开始放置
			{
				i++;
				x[i] = -1;
				j=0;
			}
		}
		else	//说明该列的所有行都不满足条件,则回溯到前一列,且位置是原来行号的下一行
		{
			j = x[i-1] + 1;
			i--;
		}
	}
}
void Queen_n(int n)
{
	int *X = new int[n];
	int sum = 0;
	for(int i=0;i<n;i++)
		X[i] = -1;//X[i]表示第i列上,皇后所在的行号
	//BackTracing(X,sum,0,n);	//递归方法
	Back_not_resur(X,sum,n);//非递归解法
	printf("sum = %d\n",sum);
	delete []X;
	
}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/leepwang/article/details/7682640
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞