N皇后问题

一、N皇后问题

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。

你的任务是,对于给定的N,求出有多少种合法的放置方法。

input

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

Output

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

Sample

Inputcopy

Outputcopy

1
8
5
0

1
92
10

思路:

  1. 可以先从第一行开始,然后逐渐dfs下一行

  1. 放置皇后需要满足:不允许在同一排或者同一列或者主副对角线上

  1. 用打表来存储答案,防止超时问题

ps:row:行 ,db[N]打表存储不同的n放置的皇后的个数

主副对角线规律

主对角线:row+i(类似:y=-x+b,可得:b=y+x)

副对角线:row-i+n;(类似:y=x+b,可得:b=y-x+n)

ps:加n是因为数组中没有负数

代码1:

#include<bits/stdc++.h>
using namespace std;
const int N=200;
int a[N],db[N]; 
int n,cnt=0;
//int nex[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
bool check(int x,int y)
{
    for(int i=1;i<=x;i++)
    {
        if(a[i]==y) return false;
        if(i+a[i]==x+y) return false;
        if(i-a[i]==x-y) return false;
    }
    return true;
}
void dfs(int row)
{
    if(row==n+1)
    {
        cnt++;
        return ;
    }
    for(int i=1;i<=n;i++)
    {    
        if(check(row,i))
        {
            a[row]=i;
            dfs(row+1);
            a[row]=0;
        }
    }
}
int main()
{
    for(n=1;n<=10;n++)
    {
        cnt=0;
        dfs(1);
        db[n]=cnt;
    }
    while(~scanf("%d",&n)&&(n!=0))
    {
        printf("%d\n",db[n]);
    }
    return 0;
}

二、搜索

题目描述

DFS全称是Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法。所谓深度优先,就是说每次都尝试向更深的节点走。 常常用来指代用递归函数实现的搜索,最显著的特征在于其递归调用自身。DFS 会对其访问过的点打上访问标记,在遍历图时跳过已打过标记的点, 以确保每个点仅访问一次。符合以上两条规则的函数,便是广义上的 DFS。

对于一个6×6的棋盘,有六个棋子被放置在棋盘上,要求任意两个棋子都不能处于同一行、同一列或同一斜线上。 第i个数字表示在第 i 行的相应位置有一个棋子,如下: 行号 1 2 3 4 5 6 列号 2 4 6 1 3 5 这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。 并把它们以上面的序列方法输出,解按字典顺序从小到大排列。(字典序是基于字母顺序排列的单词按字母顺序排列的方法。例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。) 请输出前3个解。最后一行是解的总个数。

输入描述

一行一个正整数n,表示棋盘是 n×n 大小的。

输出描述

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

样例输入

6

样例输出

2 4 6 1 3 5

3 6 2 5 1 4

4 1 5 2 6 3

4

数据范围

6≤n≤13

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=200;
int a[N],x[N],y[N],zhu[N],fu[N]; 
int n,cnt=0;
void print()
{
    if(cnt<=3)
    {
        for(int i=1;i<=n;i++)
            printf("%d ",a[i]);
        printf("\n"); 
    }
}
void dfs(int row)
{
    if(row>n)
    {
        cnt++;
        print();
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!x[row]&&!y[i]&&!zhu[row+i]&&!fu[row-i+n])
        {
            a[row]=i;
            x[row]=i;
            y[i]=zhu[row+i]=fu[row-i+n]=1;
            dfs(row+1);
            x[row]=0;
            y[i]=zhu[row+i]=fu[row-i+n]=0;
        }
    }
}
int main()
{
    cnt=0;
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",cnt);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值