• [ACM] hdu 2553 N皇后问题


    N皇后问题

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 11   Accepted Submission(s) : 3

    Font: Times New Roman | Verdana | Georgia

    Font Size:

    Problem Description

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

    Input

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

    Output

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

    Sample Input

    1
    8
    5
    0
    
    

    Sample Output

    1
    92
    10
    
    

    Author

    cgf

    Source

    2008 HZNU Programming Contest
     

    思路分析:

    本题用到了递归,一遇到递归就头疼,不知道递归到哪里去了。针对该题,我把N=4的情况,把递归完全跑了一遍,在纸上画来画去,终于对该题递归的过程有了一定的理解。在递归的同时也进行回溯。下面代码中行数和列数均是从0开始的。这里写思路为了好理解,我们认为行数和列数均是从1开始的。整体思路是一行一行的放,在每一行中一列一列的放。这里的n设为4,先放第一行,从第一列开始,外层一个循环,从第1列到第n列,但是程序还没有跑到第n列(这里,第一行放在第一列就符合题意),代码中一个递归,就跳到第二行里去了search(1+1),该放第二行了,外层一个循环,从第1列到第n列,再用一个for循环检查放的位置是否合适,第二行放在第一列肯定不行(和第一行同列),放在第二列也不行(和第一行对角线),放在第三列可以,这时候外层循环也没有跑完,就进入了一个新的递归,跳到第三行里去了search(2+1),该放第三行了,外层一个循环,放在第一列不行,第二列也不行,第三列也不行,第四列也不行。循环结束,没有执行里面的search(3+1),第三行哪里也不能放,回溯,又跑到第二行的状态去,还记得第二行里面的那个外层循环没有跑完吗,上面跑到了第三列,于是接着循环,放在第四列,可以放,又进入一个新的递归,search(2+1),即刚才说的哪里都不能放的第三行,又一个循环,从第一列开始放,第一列不行,第二列可以,这时候在第三行外层循环在第二列的时候,又进入了新的递归search(3+1),寻找下一行,接着又一个外循环。。。。如果不行,又跳到第三行。。。接下来就不说了,已经说了这么多,大体的流程就是这样的,不断的递归,不断的回溯,(因为上一行的循环还没有执行完)。

    代码:

    #include <iostream>
    #include <string.h>
    using namespace std;
    
    int c[11],tot,n;
    
    void search(int cur)//不符合条件就回溯
    {
        int i,j;
        if(cur==n) tot++;//当search(n-1)时也成功,说明有符合题意的情况,所以search(n-1)里面有search(n)执行时,tot++
        else for(i=0;i<n;i++)//当前行放在第几列上。
        {
            int ok=1;
            c[cur]=i;//当前行放在第几列上。
            for(j=0;j<cur;j++)//j<cur不是j<i一定要注意!!!
                if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j])//检查是否在同一列(列数相等),左对角线(行数-列数相等),右对角线(行数+列数相等)
            {
                ok=0;
                break;//不行,尝试放在下一列上。跳到(i=0;i<n;i++)那里去。
            }//该循环只起到检查的作用
            if(ok)
                search(cur+1);//当前可以放在该列,搜索下一行,但注意,当前行的最外层循环还没有跑完,即当前行放在哪一列还没有完全的遍历,当下一行搜索不成功时,回溯到当前行继续放在下一列。
        }
    }
    
    int main()
    {
        int num[11];//进行预处理,否则会超时。
        for(int i=1;i<=10;i++)
        {
            n=i;
            search(0);
            num[i]=tot;
            tot=0;
        }
        while(cin>>n&&n)
        {
            cout<<num[n]<<endl;
        }
        return 0;
    }
    

  • 相关阅读:
    "用脑思考"和"用心感知"
    Oracle 分页查询
    MySQL定时执行存储过程
    java商城小程序收藏
    巴士团小程序
    微信小程序this作用域
    Flink之API的使用(3):Source的使用
    Flink之API的使用(2):Transform算子的使用
    Flink之API的使用(1):Sink的使用
    Flink之基础内容(2):DataStream的创建和使用
  • 原文地址:https://www.cnblogs.com/sr1993/p/3697969.html
Copyright © 2020-2023  润新知