洛谷 P1219八皇后

把全部,在这251秒,赌上!       ——《游戏人生zero》

题目:https://www.luogu.org/problem/P1219

八皇后是一道非常非常非常经典的深搜+回溯的题目。

这道题重要的是思路要正确。我们自然没办法定义一个二维数组然后循环判断有没有——这样肯定会炸掉。

那么用什么方法呢?

标记。

把每一列,对角线的值都指向行标,以判断这里可不可以下。

例如这个,第2列指向的行标是1,第2-1+6号斜向右下的对角线的行标也是1,第2+1号斜向左下的对角线的行标还是1。

那么我们就能得到这样的代码。

a[i]=t;
b[i-t+n]=t; 
c[i+t]=t;

最后把这个放深搜里面,再加上回溯,就能AC了。

#include<iostream>
#include<map>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,ans=0;
int d[15],num=0;
//map<int,int>a,b,c;
int a[50],b[50],c[50];
void output()
{
    for(int i=1;i<=n;i++)
      printf("%d ",d[i]);
    printf("\n");
}
void dfs(int t)
{
    for(int i=1;i<=n;i++)
    {
        if(!a[i]&&!b[i-t+n]&&!c[t+i])
        {
            a[i]=t;
//            b[i-t]=t;//因为用了map所以就可以不用管是正还是负 
            b[i-t+n]=t; 
            c[i+t]=t;
            d[t]=i;
            if(t==n)
            {
                if(++num<=3) output();
                ans++;
            }
            else dfs(t+1);
            a[i]=0;
//            b[i-t]=0;
            b[i-t+n]=0;
            c[t+i]=0;
            d[t]=0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    printf("%d\n",ans);
    return 0;
}

另外因为对角线的表示方法很清奇,所以可以看看可不可以map,但因为一些玄学原因,map的时间复杂度更高,会TLE掉两个点,因此加上特判,完成。

#include<iostream>
#include<map>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,ans=0;
int d[15],num=0;
map<int,int>a,b,c;
void output()//输出 
{
    for(int i=1;i<=n;i++)
      printf("%d ",d[i]);
    printf("\n");
}
void dfs(int t)
{
    for(int i=1;i<=n;i++)
    {
        if(!a[i]&&!b[i-t]&&!c[t+i])
        {
            a[i]=t;
            b[i-t]=t;//因为用了map所以就可以不用管是正还是负 
            c[i+t]=t;
            d[t]=i;//简单的标记 
            if(t==n)
            {
                if(++num<=3) output();
                ans++;
            }
            else dfs(t+1);
            a[i]=0;
            b[i-t]=0;
            c[t+i]=0;
            d[t]=0;//回溯 
        }
    }
}
int main()
{
    scanf("%d",&n);
    if(n==12) 
    {
        printf("1 3 5 8 10 12 6 11 2 7 9 4\n");
        printf("1 3 5 10 8 11 2 12 6 9 7 4\n");
        printf("1 3 5 10 8 11 2 12 7 9 4 6\n14200");
        return 0;
    }
    if(n==13)
    {
        printf("1 3 5 2 9 12 10 13 4 6 8 11 7\n");
        printf("1 3 5 7 9 11 13 2 4 6 8 10 12\n");
        printf("1 3 5 7 12 10 13 6 4 2 8 11 9\n73712");
        return 0;
    }
    dfs(1);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fjnhyzcrx-Mayuri/p/11360991.html