杭电ACM——2533,N皇后问题(搜索)

突破口:
N*N的棋盘放置N个皇后,因为皇后的特性,合法的放置方法中每行(每列)必定有一个皇后,因此我们可以先搜索第1行可以放置的位置,再逐步搜索第2行,直到第N行。而不用去穷举第一个棋子在棋盘中的位置,这样做是会超时,而且会重复运算的。

代码如下:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
char s[11][11];		//模拟棋盘,s[i][j]='0'说明这里可以放置一个皇后,否则则不行
int N,cnt;
void func(int x,int y,int flag)		//将皇后所在的行,列,主副对角线全部进行处理,使它们不能够被放置皇后或者恢复原样
{
	int i,j;
	for(i=1;i<=N;i++)
	{
		s[i][y]+=flag;
		s[x][i]+=flag;
	}
	for(i=x+1,j=y+1;i<=N&&j<=N;i++,j++)
		s[i][j]+=flag;
	for(i=x-1,j=y-1;i>=1&&j>=1;i--,j--)
		s[i][j]+=flag;
	for(i=x+1,j=y-1;i<=N&&j>=1;i++,j--)
		s[i][j]+=flag;
	for(i=x-1,j=y+1;i>=1&&j<=N;i--,j++)
		s[i][j]+=flag;
 }
void place(int row,int num)		//搜索,row记录当前所在行,num记录当前下的皇后个数
{
	if(num==N)		//num=N,cnt++,就可以结束了
	{
		cnt++;
		return; 
	}
	if(row>N)		//不可越界
		return;
	int i,j;
	for(i=1;i<=N;i++)
	{
		if(s[row][i]=='0')
		{
			func(row,i,1);		//处理
			s[row][i]='Q';
			place(row+1,num+1);
			func(row,i,-1);		//恢复
			s[row][i]='0';
		}
	}
 }
int main()
{
	int ans[11]={0,1,0,0};		//1~3的情况很容易分析出来
	int i,j;
	for(i=0;i<=10;i++)
		for(j=0;j<=10;j++)
			s[i][j]='0';
	for(i=4;i<=10;i++)
	{
		N=i;cnt=0;
		place(1,0);
		ans[i]=cnt;//cout<<ans[i]<<endl;
	}
	while((cin>>N)&&N)
		cout<<ans[N]<<endl;
	return 0;
 } 

猜你喜欢

转载自blog.csdn.net/shamansi99/article/details/89917806