HDU 2553 N皇后问题 | 搜索 | dfs

本来想刷kuangbin专题的……结果专题一第一题就卡了,看到推荐说可以先复习一下八皇后问题,发现太久不写搜索我已经是屑了orz

题意:在N*N的棋盘上,给出N个棋子,同行、同列、同对角线只可以放一个,问有多少种不同的排列方法。
要用搜索我们都知道,但是把什么设为dfs的参数呢?

最开始设置的是x,y,rest,标记当前位置和剩余棋子数量,但是把我自己绕进去了,搞了半天也没法保证全部扫到,并且写的时候忽略了对角线是有两个方向的。在这道题里面,行列均唯一,所以其实关于定位的参数只需要x,y中一个就可以,如果有两个到时候还要分八个方向移动(但是其实没有必要)。关于对角线的判断,最开始我是用while一遍遍扫,也非常麻烦。
看了题解之后觉得处理方法很巧妙:

  • 只记录行,不需要rest,用行兼顾rest的作用(逐行扫,扫到n行时即完成)
  • 用三维数组mark[3][],第一维分别表示两种对角线和列
  • 对角线的规律:主对角线行列差相同(为了排除负数+N),次对角线行列和相同。

最后,太久不写,我自己搞的时候回溯的位置搞得乱七八糟,仔细品味一下这里,我们是先判断当前位置是否合法(dfs的时候不判断,递归进来再判断),假如合法,先改变标记(标记为已经走过),向下dfs,再抹去标记。在这里,下一位置的试探是通过i的循环控制的,我们相当于定住了行,改变i来在列之间移动,兼用mark[3][]判断这一位置是否合法。
P.S.1000MS 要预处理

#include <bits/stdc++.h>

using namespace std;

int N, tans;//N <= 10   N*N棋盘上N个皇后
int mark[3][25], ans[11];

void dfs(int row)
{
    if(row == N+1)
    {
        tans++;
        return;
    }

    for(int i = 1;i <= N;i++)
    {
        if(mark[0][row - i + N] == 0 && mark[1][i] == 0 && mark[2][i + row] == 0)
        {
            mark[0][row - i + N] = mark[1][i] = mark[2][i + row] = 1;
            dfs(row+1);
            mark[0][row - i + N] = mark[1][i] = mark[2][i + row] = 0;
        }
    }

}


int main()
{
    for(int i = 1;i <= 10;i++)
    {
        tans = 0, N = i;
        memset(mark, 0, sizeof(mark));
        dfs(1);
        ans[i] = tans;
    }


    while(scanf("%d", &N) && N != 0)
    {
        printf("%d\n", ans[N]);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值