八皇后问题

八皇后问题

第一个博客,好鸡儿激动
咳咳,本菜鸡写了半天的代码,大佬轻喷
所谓八皇后问题就是在8*8的棋盘中放置八个皇后,保证每行每列每条斜线都只有一个皇后,典型的dfs深搜,不过实现起来也不是轻而易举的,此前需要一定的规划
我们定义如下变量:
1.int chess[8]用来记录每行皇后的纵坐标(每行肯定有且只有一个,所以不用管横坐标),-1表示还未落在棋盘上
2.int mp[8][8]棋盘
3.int mem[8][8]用来标记每个棋子是否已经落过这个点
我们定义如果mp[i][j]在某个皇后的攻击范围内,则该点的值大于0,否则等于0,如果某个皇后已经落过了某个点,则mem[i][j]=1,否则=0
下面是思路:
dfs(int t)//表示轮到第t个皇后上场了(t从0到7)
1.如果该皇后在场上,则取出
2.在该行上找不在其他皇后攻击范围内且没有标记的点
①存在该点
将皇后落至该点并标记该点
t++
若t=8则将当前情况保存下来,t–
dfs(t)
②不存在该点
将当前整行的标记全部取消(接下来将回退至上一个皇后,这意味着当前皇后走过的点只要之前的皇后布置有所变动,则该皇后落在之前走过的点也不会引起重复)
t–
若t=-1则所有情况已遍历完(第一个皇后已经走到第八列了)
否则dfs(t)
代码如下

#include<iostream>
#include<string.h>
using namespace std;
int a[100][8],anum=0;//用来保存满足条件的情况中皇后的列坐标

int chess[8];//每个皇后的列坐标 ,-1表示未加入棋盘 
int mp[8][8];
int mem[8][8];//标记 
void PUT(int x,int y)
{
	for(int i=0;i<8;i++)
	{
		mp[x][i]++;
		mp[i][y]++;
	}
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i++,j++)
	mp[i][j]++;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i++,j--)
	mp[i][j]++;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i--,j++)
	mp[i][j]++;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i--,j--)
	mp[i][j]++;
}
void PULL(int x,int y)
{
	for(int i=0;i<8;i++)
	{
		mp[x][i]--;
		mp[i][y]--;
	}
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i++,j++)
	mp[i][j]--;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i++,j--)
	mp[i][j]--;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i--,j++)
	mp[i][j]--;
	for(int i=x,j=y;i>=0&&i<8&&j>=0&&j<8;i--,j--)
	mp[i][j]--;
}
void dfs(int t)
{
	if(chess[t]>=0)
	PULL(t,chess[t]);//很重要,别忘了 
	int x=-1;
	for(int i=0;i<8;i++)
	if(mp[t][i]==0&&mem[t][i]==0)
	{
		x=i;
		break;
	}
	if(x>=0)
	{
		chess[t]=x;
		PUT(t,x);
		mem[t][x]=1;
		t++;
		if(t==8)
		{
			for(int i=0;i<8;i++)
			a[anum][i]=chess[i];
			anum++;
			t--;
		}
		dfs(t);
	}
	else
	{
		chess[t]=-1;
		for(int i=0;i<8;i++)
		mem[t][i]=0;
		t--;
		if(t>=0)
		dfs(t);
	}
}
int main()
{
	memset(mp,0,sizeof(mp));
	memset(mem,0,sizeof(mem));
	memset(chess,-1,sizeof(chess));
	dfs(0);
	cout<<anum<<endl;
	for(int i=0;i<anum;i++)
	{
		for(int j=0;j<8;j++)
		cout<<a[i][j]<<" ";
		cout<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值