算法设计(一) : 搜索算法实现八皇后问题

  • Post author:
  • Post category:其他




写在开头:实验结果截图8皇后太多截不完,用4皇后代替了,只需将n->8就行



图解算法过程:

在这里插入图片描述

下面分析中的



(

x

,

y

)

(x,y)






(


x


,




y


)





相当于上面的



(

u

,

i

)

(u,i)






(


u


,




i


)






反对角线



y

=

x

+

b

y=x+b






y




=








x




+








b





, 截距



b

=

y

x

b=y−x






b




=








y













x





,因为我们要把



b

b






b





当做数组下标来用,显然



b

b






b





不能是



的,所以我们

加上 n

(实际上



+

n

+

4

+n+4






+


n




+








4





,



+

2

n

+2n






+


2


n





都行),来保证是结果是正的,即



y

x

+

n

y – x + n






y













x




+








n






而对角线



y

=

x

+

b

y=−x+b






y




=











x




+








b





截距是



b

=

y

+

x

b=y+x






b




=








y




+








x





,这里截距一定是



的,所以

不需要加偏移量


核心目的:找一些合法的下标来表示

dg



udg

是否被标记过,所以如果你愿意,你取

udg[n−u+i]

也可以,只要所有

(u,i)

对可以映射过去就行



算法一:DFS 按行枚举,时间复杂度O(n!)

const int N=25;
int n;
char g[N][N];
bool dg[N],udg[N],col[N];//对角线 dg[u+i],反对角线udg[n−u+i]中的下标 u+i和 n−u+i 表示的是截距
int k=1;
void dfs(int u)
{
	if(u==n)
	{
		cout<<n<<"皇后的第"<<k++<<"种方案:"<<endl;
		for(int i=0;i<n;i++)
				cout<<g[i]<<endl;
		cout<<endl;
		return; 
	}
	for(int i=0;i<n;i++)
	{
		if(!col[i]&&!dg[u+i]&&!udg[n-u+i])
		{
			g[u][i]='Q';
			col[i]=dg[u+i]=udg[n-u+i]=true;//标记 
			dfs(u+1);
			col[i]=dg[u+i]=udg[n-u+i]=false;//还原现场
			g[u][i]='.'; 
		}
	}
}
void solve()
{
	cin>>n;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			g[i][j]='.';
	dfs(0);
}



运行结果截图:

在这里插入图片描述

在这里插入图片描述



算法二:DFS按每个元素枚举 时间复杂度



O

(

2

n

2

)

O(2^{n^2})






O


(



2












n










2

















)





,每个位置都有两种情况,总共有



n

2

n^2







n










2












个位置

const int N=25;
int n;
char g[N][N];
bool dg[N],udg[N],col[N],row[N];
int k=1;
void dfs(int x,int y,int s)
{
	if(y==n)y=0,x++;
	if(x==n)
	{
		if(s==n)
		{
			cout<<n<<"皇后的第"<<k++<<"种方案:"<<endl;
			for(int i=0;i<n;i++)
				cout<<g[i]<<endl;
			cout<<endl;
		}
		return;
	}
	if(!row[x]&&!col[y]&&!dg[x+y]&&!udg[x-y+n])//选 
	{
		g[x][y]='Q';
		row[x]=col[y]=dg[x+y]=udg[x-y+n]=true;
		dfs(x,y+1,s+1);
		row[x]=col[y]=dg[x+y]=udg[x-y+n]=false;
		g[x][y]='.';
	}
	//不选
	dfs(x,y+1,s); 
}
void solve()
{
	cin>>n;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			g[i][j]='.';
	dfs(0,0,0);
}



运行结果截图

在这里插入图片描述

在这里插入图片描述



算法三:二进制对空间进行优化

int lowbit(int x){return x&-x;}//最低位1及其后面的0构成的数值
const int N=25;
int n;
vector<string>g;
vector<vector<string>>res;
int cnt=1;
void dfs(int a,int b,int c,int k)
{
	if(k==n)
	{
		res.push_back(g);
		return;
	}
	for(int i=~(a|b|c)&((1<<n)-1);i;i-=lowbit(i))
	{
		int p=lowbit(i);
		g[k][log2(p)]='Q';//计算第几位是1,用对数函数log2十分方便
		dfs((a|p)<<1,(b|p)>>1,c|p,k+1);
		g[k][log2(p)]='.';
	}
}
void solve()
{
	cin>>n;
	vector<string>board(n,string(n,'.'));
	g=board;
	dfs(0,0,0,0);
	for(int i=0;i<res.size();i++)
	{
		cout<<n<<"皇后的第"<<cnt++<<"种方案:"<<endl;
		for(int j=0;j<res[i].size();j++)
		{
			cout<<res[i][j]<<endl;
		}
		cout<<endl;
	}
}



运行结果截图

在这里插入图片描述

在这里插入图片描述



版权声明:本文为qq_52765554原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。