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 ;
}

 

你可能感兴趣的:(八皇后)