• 洛谷 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("
    ");
    }
    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
    ",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("
    ");
    }
    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
    ");
            printf("1 3 5 10 8 11 2 12 6 9 7 4
    ");
            printf("1 3 5 10 8 11 2 12 7 9 4 6
    14200");
            return 0;
        }
        if(n==13)
        {
            printf("1 3 5 2 9 12 10 13 4 6 8 11 7
    ");
            printf("1 3 5 7 9 11 13 2 4 6 8 10 12
    ");
            printf("1 3 5 7 12 10 13 6 4 2 8 11 9
    73712");
            return 0;
        }
        dfs(1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    234. Palindrome Linked List(判断链表是否回文)
    141. Linked List Cycle(判断链表是否有环)
    第二届“中国高校计算机大赛-大数据挑战赛” 20名
    Spark集群 Python Package管理
    Android中单选框RadioButton的基本用法
    【Android】进程间通信IPC——Binder
    Spring Boot 集成 JWT 实现单点登录授权
    pythonGUI编程——Qt库(1)
    Android获取SD卡路径/内存的几种方法
    Android主题更换换肤
  • 原文地址:https://www.cnblogs.com/fjnhyzcrx-Mayuri/p/11360991.html
Copyright © 2020-2023  润新知