八皇后问题(递归、非递归——回溯)

首先,让我们先来温习递归:

调用前

一个函数的运行期间调用另一个函数时,在运行 被调用函数之前,系统需要完成3件事情:
(1)将所有的 实参、返回地址等信息传递给 被调用函数保存;
(2)为 被调用函数局部变量分配存储区;
(3)将控制转移到被调函数的入口。

调用中

而从 被调用函数返回调用函数之前,系统也应完成3件工作:
(1)保存被调函数的计算结果;
(2)释放被调函数的数据区;
(3)依照被调函数保存的返回地址将控制转移到调用函数。当有多个函数构成 嵌套调用时,按照后调用先返回的原则。
  


会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入:

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

输出:

输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

样例输入:

2
1
92
样例输出:
15863724
84136275
#include <stdio.h>

int nCount=0;

int judge(int (*chess)[8],int row,int n)
{

	int i,j,flag0=0,flag1=0,flag2=0,flag3=0,flag4=0;

	//列
	for(i=0;i<8;i++)
	{
		if (*(*(chess+i)+n)==1)
		{
			flag0=1;
			break;
		}
	}
	//左上
	for(i=row,j=n;i>=0 && j>=0;j--,i--)
	{
		if (*(*(chess+i)+j)==1)
		{
			flag1=1;
			break;
		}
	}
	//左下
	for(i=row,j=n;i<8 && j>=0 ;j--,i++)
	{
		if (*(*(chess+i)+j)==1)
		{
			flag2=1;
			break;
		}
	}
	//右上
	for(i=row,j=n; i>=0 && j<8;j++,i--)
	{
		if (*(*(chess+i)+j)==1)
		{
			flag3=1;
			break;
		}
	}
	//右下
	for(i=row,j=n; i<8 && j<8 ;j++,i++)
	{
		if (*(*(chess+i)+j)==1)
		{
			flag4=1;
			break;
		}
	}
	if (flag0 || flag1 || flag2 || flag3 || flag4)
	{
		return 0;
	}
	return 1;
}

void eightQueen(int (*chess)[8],int row,int n)
{

	int chess2[8][8],i,j;
	
		for (i=0;i<8;i++)
		{
			for (j=0;j<8;j++)
			{
				
				chess2[i][j]=chess[i][j];
			}
		}		
	if (row==8)
	{
		printf("第%d种解法是:\n",++nCount);
		for (i=0;i<8;i++)
		{
			for (j=0;j<8;j++)
			{
				
				printf("%d ",*(*(chess2+i)+j));
			}
			printf("\n");
		}
	}else
	{

		for (i=0;i<n;i++)
		{
		if (judge(chess,row,i))//判断皇后是否可放非零可放
			{
				
			for (j=0;j<8;j++)
			{
				*(*(chess2+row)+j)=0;
			}
				*(*(chess2+row)+i)=1;
				

				eightQueen(chess2,row+1,8);
				

			}
		}
	}

}

int main()
{
	int chess[8][8];
	int i,j;
	for (i=0;i<8;i++)
	{
		for (j=0;j<8;j++)
		{
			chess[i][j]=0;
		}
	}

	eightQueen(chess,0,8);

	return 0;
}



再来一个剪枝的回溯法吧:

#include <stdio.h>
#include <string.h>

int nCount;

bool isPlace(int row,int col,int (*queen)[8])
{
	int i,j;
	//判断行
	for (i=0;i<8;i++)
	{
		if (1==queen[i][col])
		{
			return false;
		}
	}
	//判断列
	for (i=0;i<8;i++)
	{
		if (1==queen[row][i])
		{
			return false;
		}
	}
	//判断左上
	for (i=row-1,j=col-1;i>=0 && j>=0;i--,j--)
	{
		if (1==queen[i][j])
		{
			return false;
		}
	}
	//判断左下
	for (i=row+1,j=col-1;i<8 && j>=0;i++,j--)
	{
		if (1==queen[i][j])
		{
			return false;
		}
	}
	//判断右上
	for (i=row-1,j=col+1;i>=0 && j<8;i--,j++)
	{
		if (1==queen[i][j])
		{
			return false;
		}
	}
	//判断右下
	for (i=row+1,j=col+1;i<8 && j<8;i++,j++)
	{
		if (1==queen[i][j])
		{
			return false;
		}
	}
	return true;
}


void Q(int k,int (*queen)[8])
{
	int i,j;
	if (k==8)
	{
		for (i=0;i<8;i++)
		{
			for (j=0;j<8;j++)
			{
				printf("%d ",queen[i][j]);
			}
			printf("\n");	
		}
		printf("\n");
		nCount++;
	}else
	{
		for (i=0;i<8;i++)
		{
			if (isPlace(i,k,queen))
			{
				queen[i][k]=1;
				Q(k+1,queen);
				queen[i][k]=0;
			}
		}
	}

}

int main()
{
	int queen[8][8];
	int i,j;
	for (i=0;i<8;i++)
	{
		for (j=0;j<8;j++)
		{
			queen[i][j]=0;
		}
	}
	Q(0,queen);
	printf("the number of the answers are %d\n",nCount);
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值