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

 

    原文作者:InfantSorrow
    原文地址: https://www.cnblogs.com/CCBB/archive/2011/09/14/2176692.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞