zoukankan      html  css  js  c++  java
  • 2754 八皇后

    问题描述:http://poj.grids.cn/practice/2754/

    2754 - 八皇后

    Time Limit:
    1000ms
    Memory limit:
    65536kB

    题目描述
    会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。
    如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
    对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。
    已经知道8皇后问题一共有92组解(即92个不同的皇后串)。给出一个数b,要求输出第b个串。
    串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

    输入
    第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

    输出
    输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。
    样例输入

    2
    1
    92

    样例输出

    15863724
    84136275 

    首先是用了迭代法,把八层循环都列了出来。。 循环太多了,各种复制粘贴和查找替换。。最后内存252kb,时间0ms

    /********************************************************************************************************
    解题思路:

    经典方法用的是递归和回溯,穷举所有情况。我用了八层的迭代来试试,主要要找一个高效的,
    判定当前棋子是否能够安全放置的方法,并且拿掉此棋子还能够还原它对其他棋子的影响。

    按照每行来迭代,自然不考虑行的限制。

    用一个标识数组column[8]来判断当前列是否能够放棋子,并且保存受到了几个棋子的影响,
    如果受到多个棋子影响了,回溯时拿掉一个棋子,不会影响其他棋子的影响。

    用另2个标识数组diagonal_1[15]和diagonal_2[15]来判断当前右斜线和左斜线分别能否放棋子。
    对于棋子board[i][j],所在右斜线用diagonal_1[j-i+7]表示,左斜线用diagonal_2[i+j]表示。

    内存:252kB
    时间:0ms
    *******************************************************************************************************
    */

    #include 
    <iostream>
    #include 
    <cmath>
    #include 
    <cctype>
    #include 
    <string>
    #include 
    <map>
    #include 
    <set>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    <list>
    #include 
    <stack>
    #include 
    <cstring>
    //#include <stdlib.h>
    //#include <iomanip>

    using namespace std;

    inline 
    void add_chess(unsigned column[], unsigned diagonal_1[], unsigned diagonal_2[], int i, int j)
    {
        column[j]
    ++;
        diagonal_1[j
    -i+7]++;
        diagonal_2[i
    +j]++;
    }

    inline 
    void cancel_chess(unsigned column[], unsigned diagonal_1[], unsigned diagonal_2[], int i, int j)
    {
        column[j]
    --;
        diagonal_1[j
    -i+7]--;
        diagonal_2[i
    +j]--;
    }

    int main()
    {
        
    //存放所有结果
        unsigned answers[92][8];
        
    //存放一次结果
        unsigned count = 0, hang[8= {0};

        
    //用来记录当前的列是否可以放棋子
        unsigned column[8= {0};
        unsigned diagonal_1[
    15= {0}, diagonal_2[15= {0};

        
    //////////////////////////////////////////////////////////////////////////
        //枚举所有情况,并且剪枝+回溯
        
    //第0层循环
        for (hang[0= 0; hang[0< 8; hang[0]++)
        {
            add_chess(column, diagonal_1, diagonal_2, 
    0, hang[0]);
            
    //第1层循环
            for (hang[1= 0; hang[1< 8; hang[1]++)
            {
                
    if (column[hang[1]] == 0 && diagonal_1[hang[1]+6== 0 && diagonal_2[hang[1]+1== 0)
                {
                    add_chess(column, diagonal_1, diagonal_2, 
    1, hang[1]);
                    
    //第2层循环
                    for (hang[2= 0; hang[2< 8; hang[2]++)
                    {
                        
    if (column[hang[2]] == 0 && diagonal_1[hang[2]+5== 0 && diagonal_2[hang[2]+2== 0)
                        {
                            add_chess(column, diagonal_1, diagonal_2, 
    2, hang[2]);
                            
    //第3层循环
                            for (hang[3= 0; hang[3< 8; hang[3]++)
                            {
                                
    if (column[hang[3]] == 0 && diagonal_1[hang[3]+4== 0 && diagonal_2[hang[3]+3== 0)
                                {
                                    add_chess(column, diagonal_1, diagonal_2, 
    3, hang[3]);
                                    
    //第4层循环
                                    for (hang[4= 0; hang[4< 8; hang[4]++)
                                    {
                                        
    if (column[hang[4]] == 0 && diagonal_1[hang[4]+3== 0 && diagonal_2[hang[4]+4== 0)
                                        {
                                            add_chess(column, diagonal_1, diagonal_2, 
    4, hang[4]);
                                            
    //第5层循环
                                            for (hang[5= 0; hang[5< 8; hang[5]++)
                                            {
                                                
    if (column[hang[5]] == 0 && diagonal_1[hang[5]+2== 0 && diagonal_2[hang[5]+5== 0)
                                                {
                                                    add_chess(column, diagonal_1, diagonal_2, 
    5, hang[5]);
                                                    
    //第6层循环
                                                    for (hang[6= 0; hang[6< 8; hang[6]++)
                                                    {
                                                        
    if (column[hang[6]] == 0 && diagonal_1[hang[6]+1== 0 && diagonal_2[hang[6]+6== 0)
                                                        {
                                                            add_chess(column, diagonal_1, diagonal_2, 
    6, hang[6]);
                                                            
    //第7层循环
                                                            for (hang[7= 0; hang[7< 8; hang[7]++)
                                                            {
                                                                
    if (column[hang[7]] == 0 && diagonal_1[hang[7]] == 0 && diagonal_2[hang[7]+7== 0)
                                                                {
                                                                    
    //添加一组解
                                                                    memcpy(answers[count], hang, sizeof(unsigned)*8);
                                                                    count
    ++;
                                                                }
                                                            }
                                                            cancel_chess(column, diagonal_1, diagonal_2, 
    6, hang[6]);
                                                        }
                                                    }
                                                    cancel_chess(column, diagonal_1, diagonal_2, 
    5, hang[5]);
                                                }
                                            }
                                            cancel_chess(column, diagonal_1, diagonal_2, 
    4, hang[4]);
                                        }
                                    }
                                    cancel_chess(column, diagonal_1, diagonal_2, 
    3, hang[3]);
                                }
                            }
                            cancel_chess(column, diagonal_1, diagonal_2, 
    2, hang[2]);
                        }
                    }
                    cancel_chess(column, diagonal_1, diagonal_2, 
    1, hang[1]);
                }
            }
            cancel_chess(column, diagonal_1, diagonal_2, 
    0, hang[0]);
        }

        
    //////////////////////////////////////////////////////////////////////////
        //输入结果
        int n, tmp;
        cin 
    >> n;
        
    while (n--)
        {
            cin 
    >> tmp;
            
    for (int i = 0; i < 8; i++)
                cout 
    << answers[tmp-1][i]+1;
            cout 
    << "\n";
        }

        
    return 0;
    }

    然后用了经典的递归和回溯的方法,深度优先搜索一个八叉树。最后内存256kb,时间0ms

    #include <iostream>
    #include 
    <cmath>
    #include 
    <cctype>
    #include 
    <string>
    #include 
    <map>
    #include 
    <set>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    <list>
    #include 
    <stack>
    #include 
    <cstring>
    //#include <stdlib.h>
    //#include <iomanip>

    using namespace std;

    //用来记录当前的列是否可以放棋子
    unsigned column[8= {0};
    unsigned diagonal_1[
    15= {0}, diagonal_2[15= {0};

    //存放所有结果
    unsigned answers[92][8];

    //hang存放一次结果,count记录结果个数
    unsigned ans_count = 0, hang[8= {0};

    inline 
    void add_chess(int i, int j)
    {
        column[j]
    ++;
        diagonal_1[j
    -i+7]++;
        diagonal_2[i
    +j]++;
    }

    //i, j分别是行和列
    inline void cancel_chess(int i, int j)
    {
        column[j]
    --;
        diagonal_1[j
    -i+7]--;
        diagonal_2[i
    +j]--;
    }

    inline 
    bool judge(int i, int j)
    {
        
    if (column[j] == 0 && diagonal_1[j-i+7== 0 && diagonal_2[i+j] == 0)
            
    return true;
        
    return false;
    }

    void putQueen(int ith_row)
    {
        
    //则产生了一组新解,也即树的一条路径
        if (ith_row == 8)
        {
            memcpy(answers[ans_count], hang, 
    sizeof(unsigned)*8);
            ans_count
    ++;
        }
        
    //则查找当前行的8个棋盘格,如果可以放棋子,就放一个并且进行记录,标记对其它棋子的影响
        
    //并且往下深度递归,递归完,回溯到这一处时,还要取消对其它棋子的影响标记
        for (int j = 0; j < 8; j++)
        {
            
    if (judge(ith_row, j))
            {
                hang[ith_row] 
    = j;
                add_chess(ith_row, j);
                putQueen(ith_row
    +1);
                cancel_chess(ith_row, j);
            }
        }
    }

    int main()
    {
        
    //递归所有情况,并且剪枝+回溯
        putQueen(0);

        
    //输入结果
        int n, tmp;
        cin 
    >> n;
        
    while (n--)
        {
            cin 
    >> tmp;
            
    for (int i = 0; i < 8; i++)
                cout 
    << answers[tmp-1][i]+1;
            cout 
    << "\n";
        }

        
    return 0;
    }
  • 相关阅读:
    jQuery UI炫酷雨滴落在水面上的波纹涟漪特效
    mysql_jdbc
    数据库设计---合适的就是最好的
    谈谈 .NET Reflector
    整型反序
    iOS给Model排序
    php安装zendDebug
    zTree实现地市县三级级联封装类
    rnnlm源代码分析(八)
    CSS制作响应式正方形及其应用
  • 原文地址:https://www.cnblogs.com/CCBB/p/2176692.html
Copyright © 2011-2022 走看看