问题描述: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
;
}