n皇后问题

这篇博客介绍了如何使用深度优先搜索(DFS)解决经典的N皇后问题,即在N×N的棋盘上放置N个皇后,使得它们互不攻击。提供了两种不同的C++代码实现,分别展示了在放置皇后后输出所有可能的解决方案,以及仅计算合法放置的总数。文章涵盖了多组输入的处理,并给出了样例输入和输出,帮助读者理解算法的运行过程和效率。
摘要由CSDN通过智能技术生成

题目描述

在 N\times NN×N 的方格棋盘放置了 NN 个皇后,使得它们不相互攻击(即任意 22 个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成 4545 角的斜线上。你的任务是,对于给定的 NN,求出有多少种合法的放置方法。

输入描述

输入中有一个正整数 N≤10N≤10,表示棋盘和皇后的数量

输出描述

为一个正整数,表示对应输入行的皇后的不同放置数量。

输入输出样例

示例 1

输入

5

输出

10

不用输出棋盘时:

#include<stdio.h>
#include<math.h>

//对于N行N列的棋盘,需要放N个皇后。有sum种合法的放置方法
int sum,n;
int x[20];	//存放每行对应的列 
bool vis[20],flag;	//flag:标记当前位置是否合理 

void dfs(int t)
{
	if(t>n)
	{
		sum++;
		return;
	}
	else
	{
		for(int i=1;i<=n;i++)//列举每列 
		{
			if(vis[i]==false)
			{
				flag=true;
				for(int k=1;k<t;k++)  //check范围:1~t-1行 
				{
					//如果在同一列或者对角线上 ,则该位置不合理 
					if(x[k]==i || abs(t-k)==abs(i-x[k])) //当前坐标(t,i) ,之前坐标(k,x[k])
					{
						flag=false;
						break;
					}
				}
				
				if(flag)
				{
					x[t]=i; //为每行选一个列
					vis[i]=true;
					dfs(t+1);
					vis[i]=false; 
				}
			}
		}
	}
}

int main()
{
	while(true)
	{
	sum=0;
	scanf("%d",&n);
	if(n==0)
	break;
	
 	dfs(1);
  	printf("%d\n",sum);
	}
  return 0;
}

需要输出棋盘时:

//方法1

#include<stdio.h>
#include<math.h>
#include<bits/stdc++.h>
using namespace std;

//对于N行N列的棋盘,需要放N个皇后。有sum种合法的放置方法
int sum,n;
int x[20];	//存放每行对应的列 
bool vis[20],flag;	//flag:标记当前位置是否合理 

char a[111][111];   //输出棋盘 

void dfs(int t)
{
	if(t>n)
	{
		sum++;
		for(int i = 1; i <= n; i ++)
        {
        	for(int j=1;j<=n;j++)
           		printf("%c",a[i][j]);
          printf("\n");
        }
        cout << endl; 
		return;
	}
	else
	{
		for(int i=1;i<=n;i++)//列举每列 
		{
			if(vis[i]==false)
			{
				flag=true;
        
				for(int k=1;k<t;k++)  //check范围:1~t-1行 
				{
					//如果在同一列或者对角线上 ,则该位置不合理 
					if(x[k]==i || abs(t-k)==abs(i-x[k])) //当前坐标(t,i) 
					{
						flag=false;
						break;
					}
				}
				
				if(flag)
				{
					x[t]=i; //为每行选一个列
					a[t][i] = 'Q';
					vis[i]=true;
					dfs(t+1);
					vis[i]=false; 
					a[t][i] = '.';
				}
			}
		}
	}
}

int main()
{

	sum=0;
	scanf("%d",&n);
	
	for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= n; j ++) 
        {
            a[i][j] = '.';
        }
    }
 	dfs(1);
  	printf("%d\n",sum);
	
  return 0;
}



//方法2

#include <bits/stdc++.h>
#include<iostream>
using namespace std;
 
int n,sum;
char x[20][20];
int l[20],ug[20],ng[20];
 
//t行i列 
void dfs(int t)  
{
    if(t > n)
    {
    	sum++;
        for(int i = 1; i <= n; i ++)
        {
        	for(int j=1;j<=n;j++)
           		printf("%c",x[i][j]);
          printf("\n");
        }
        cout << endl;
        return ;
    }
    for(int i = 1; i <= n; i ++)
    {
        if(!l[i] && !ug[i + t] && !ng[i - t + n])
        {
            x[t][i] = 'Q';
            l[i] = ug[i + t] = ng[i - t + n] = 1;
            dfs(t + 1);
            l[i] = ug[i + t] = ng[i - t + n] = 0;
            x[t][i] = '.';
        }
    }
 
}
int main()
{
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= n; j ++) 
        {
            x[i][j] = '.';
        }
    }
    dfs(1);
    printf("%d",sum);
    return 0;
}
 

多组输入时:

输入格式

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

输出格式

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input

1 8
5 0

Sample Output

1 92
10


int main()
{
	while(true)
	{
	sum=0;
	scanf("%d",&n);

	if(n==0)        //输入0时停止
	break;
	
 	dfs(0);
  	printf("%d\n",sum);
	}
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值