八皇后问题详细解法

问题描述:

8×8的棋盘上,放置8皇后(棋子),使两两之间互不攻击。所谓互不攻击是说任何两个皇后都要满足:

1)不在棋盘的同一行;

2)不在棋盘的同一列;

3)不在棋盘的同一对角线上。

求:8个皇后中的每一个应该摆放在哪一列。

算法分析:

数组ColumnDownUp分别用来标记冲突,Column数组代表列冲突,从Column[1]~Column[8]代表第1列到第8列,如果某列上已经有皇后,则为1,否则为0;

  数组Down代表主对角线冲突,为Down[i-j+7](行号-列号+7),主对角线共有15条,即从b[0]~b[14],如果某条主对角线上已经有皇后,则为1,否则为0;

  数组Up代表从对角线冲突,为Up[i+j](行号加列号),从对角线也有15条,即从c[0]~c[14],如果某条从对角线上已经有皇后,则为1,否则为0;

其中主对角线中行i和列j相减的规律如下图所示:


从图中可以看出,每条主对角线上的值相同且相互之间不重复,因此可以将其看成一个标志进行判断。同理,观察次对角线中行i和列j中的值,他们相加的规律如下图所示:


利用这一规律判断对角线的情况。

1)需要在棋盘的( i, j ) 位置摆放一个皇后的时候,可以通过Column数组、Down数组和Up数组的相应元素,来判断该位置是否安全;
2)当已经在棋盘的( i, j ) 位置摆放了一个皇后以后,就应该去修改Column数组、Down数组和Up数组的相应元素,把相应的列和对角线设置为不安全。
3)最后根据递归回溯的方法来实现本问题的目标。
实现函数如下:
int Queen[9]={0};			//第i行皇后所在的列;
int Column[9]={0};			//第j列是否安全,{0, 1}
int Down[15]={0};		  	//记录每一条从上到下的对角线,是否安全,{0,1}
int Up[15]={0};				//记录每一条从下到上的对角角线,是否安全,{0,1}
int num=0;					//记录解的个数



void TryQueen(int i)		// 摆放第 i 行的皇后
{
	if(i<9)
	{
		for(int j=1;j<9;j++)		// 尝试把该皇后放在每一列
		{
			if(Column[j]||Down[i-j+7]||Up[i+j-2])
				continue;	 // 失败
			Queen[i]=j;		// 把该皇后放在第j列上
			Column[j]=1;
			Down[i-j+7]=1;
			Up[i+j-2]=1;
			if(i==8)  // 已找到一种解决方案
			{
				num++;
				for(int k=1;k<9;k++)
					cout<<setw(3)<<Queen[k];
				cout<<endl;
				
				
			}
			else	
				TryQueen(i+1);    // 摆放第i+1行的皇后
			Queen[i]=0;           // 回溯,把该皇后从第j列拿起
			Column[j]=0;
			Down[i-j+7]=0;
			Up[i+j-2]=0;
		}
		
	}
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值