八皇后问题的递归与非递归算法

八皇后问题的递归与非递归算法

问题:设在初始状
态下在国际象棋棋盘上没有任何棋子(皇后)。然后顺序在第1行,第2行,…。第8行上布放棋子。在每一行中有8个可选择位置,但在任一时刻,棋盘的合法布局都必须满足3个限制条件,即任何两个棋子不得放在棋盘上的同一行、或者同一列、或者同一斜线上。

1.非递归算法:

q[n]:q[i]代表第i行的皇后在第i列
在每行插入皇后时,检查是否存在攻击。
1.检查不同列:q[i]!=q[j]
2.检查不在同一斜线上:abs(q[i]-q[j])!=abs(i-j)
abs代表正斜线反斜线都不在他们上面。

bool check(int j)//当前要插入皇后的行数 
{
	int i=0;
	while(i<j)
	{
		if(q[i]==q[j]||abs(q[i]-q[j])==abs(i-j))
		{
			return false;
		}
		i++;
	}
	return true;
}

完整代码如下:

#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#define n 8
int q[n]={-1};//第i行上的皇后在第几列
int cnt=0;
void print()
{
	int i,j;
	for(i=0;i<n;i++) 
	{
		for(j=0;j<n;j++)
		{
			if(q[i]==j)
			{
				printf("1 ");//皇后放置 
			}
			else
			{
				printf("0 ");//无皇后放置 
			}
		}
		printf("\n");
	}
	printf("\n");
}
bool check(int j)//当前要插入皇后的行数 
{
	int i=0;
	while(i<j)
	{
		if(q[i]==q[j]||abs(q[i]-q[j])==abs(i-j))
		{
			return false;
		}
		i++;
	}
	return true;
}
void queen()
{
	int i=0;
	while(i>=0)//直到回溯到第一行也找不到可以放置皇后的位置,函数结束
	{
		q[i]++;
		while(!check(i)&&q[i]<n)
		{
			q[i]++;//找到这一行能够放置皇后的列数
		}
		if(q[i]<n)
		{
			if(i==n-1)//最后一行也成功放置皇后,找到一个解
			{
				cnt++;
				print();
			}
			else
			{
				i++;
			}
		}
		else
		{
			q[i]=-1;//第i行到最后也没有找到合适的位置,初始化本行的列数
			i--;//回到上一行,从下一列开始寻找
		}
	}
}
int main()
{
	queen();
	printf("有%d种布局",cnt);
	return 0;
}

2.递归算法
col[n]:列上放的皇后
md[2n-1]:主对角线
sd[2
n-1]:次对角线
q[n]:第 i行上的皇后在第几列

将上面的数组col,md,sd初始化为0,存放皇后后设置为1
当(col[j]!=1)&&(md[i+j]!=1)&&(sd[7+i-j]!=1)(i代表行,j代表列)
即代表此处可以放置皇后。
完整代码:

#include <stdio.h>
#include <stdbool.h>
#define n 8
int col[n]={0};//列上放的皇后 
int md[2*n-1]={0};// 主对角线 
int sd[2*n-1]={0};//次对角线 
int q[n];//第 i行上的皇后在第几列
int cnt=0;
void print()
{
	int i,j;
	for(i=0;i<n;i++) 
	{
		for(j=0;j<n;j++)
		{
			if(q[i]==j)
			{
				printf("1 ");//皇后放置 
			}
			else
			{
				printf("0 ");//无皇后放置 
			}
		}
		printf("\n");
	}
	printf("\n");
	cnt++;
}
void queen(int i)
{
	int j; 
	for(j=0;j<n;j++)
	{
		if((col[j]!=1)&&(md[i+j]!=1)&&(sd[7+i-j]!=1))
		{
			q[i]=j;//放皇后
			col[j]=1;
			md[i+j]=1;
			sd[7+i-j]=1;//标记放皇后的位置 
			if(i<n-1)
			{
				queen(i+1);
			}
			else
			{
				print();
			}
			col[j]=0;
			md[i+j]=0;
			sd[7+i-j]=0;//清除标记,开始下一组查找 
		}
	}
}
int main()
{
	queen(0);
	printf("有%d种布局",cnt);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值