程序员面试题精选100题(58)-八皇后问题
2011-05-06 21:19
387 查看
题目:在
8
×
8
的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。
这就是有名的八皇后问题。解决这个问题通常需要用递归,而递归对编程能力的要求比较高。因此有不少面试官青睐这个题目,用来考察应聘者的分析复杂问题的能力以及编程的能力。
由于八个皇后的任意两个不能处在同一行,那么这肯定是每一个皇后占据一行。于是我们可以定义一个数组
ColumnIndex[8]
,数组中第
i
个数字表示位于第
i
行的皇后的列号。先把
ColumnIndex
的八个数字分别用
0-7
初始化,接下来我们要做的事情就是对数组
ColumnIndex
做全排列。由于我们是用不同的数字初始化数组中的数字,因此任意两个皇后肯定不同列。我们只需要判断得到的每一个排列对应的八个皇后是不是在同一对角斜线上,也就是数组的两个下标
i
和
j
,是不是
i-j==ColumnIndex[i]-Column[j]
或者
j-i==ColumnIndex[i]-ColumnIndex[j]
。
关于排列的详细讨论,详见本系列博客的第
28
篇,《
字符串的排列
》,这里不再赘述。
接下来就是写代码了。思路想清楚之后,编码并不是很难的事情。下面是一段参考代码:
int
g_number = 0;
void
EightQueen()
{
const
int
queens = 8;
int
ColumnIndex[queens];
for
(int
i = 0; i < queens; ++ i)
ColumnIndex[i] = i;
Permutation(ColumnIndex, queens, 0);
}
void
Permutation(int
ColumnIndex[], int
length, int
index)
{
if
(index == length)
{
if
(Check(ColumnIndex, length))
{
++ g_number;
PrintQueen(ColumnIndex, length);
}
}
else
{
for
(int
i = index; i < length; ++ i)
{
int
temp = ColumnIndex[i];
ColumnIndex[i] = ColumnIndex[index];
ColumnIndex[index] = temp;
Permutation(ColumnIndex, length, index + 1);
temp = ColumnIndex[index];
ColumnIndex[index] = ColumnIndex[i];
ColumnIndex[i] = temp;
}
}
}
bool
Check(int
ColumnIndex[], int
length)
{
for
(int
i = 0; i < length; ++ i)
{
for
(int
j = i + 1; j < length; ++ j)
{
if
((i - j == ColumnIndex[i] - ColumnIndex[j])
|| (j - i == ColumnIndex[i] - ColumnIndex[j]))
return
false
;
}
}
return
true
;
}
void
PrintQueen(int
ColumnIndex[], int
length)
{
printf("Solution %d/n"
, g_number);
for
(int
i = 0; i < length; ++i)
printf("%d/t"
, ColumnIndex[i]);
printf("/n"
);
}
出处 http://zhedahht.blog.163.com/
。
8
×
8
的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。下图中的每个黑色格子表示一个皇后,这就是一种符合条件的摆放方法。请求出总共有多少种摆法。
由于八个皇后的任意两个不能处在同一行,那么这肯定是每一个皇后占据一行。于是我们可以定义一个数组
ColumnIndex[8]
,数组中第
i
个数字表示位于第
i
行的皇后的列号。先把
ColumnIndex
的八个数字分别用
0-7
初始化,接下来我们要做的事情就是对数组
ColumnIndex
做全排列。由于我们是用不同的数字初始化数组中的数字,因此任意两个皇后肯定不同列。我们只需要判断得到的每一个排列对应的八个皇后是不是在同一对角斜线上,也就是数组的两个下标
i
和
j
,是不是
i-j==ColumnIndex[i]-Column[j]
或者
j-i==ColumnIndex[i]-ColumnIndex[j]
。
关于排列的详细讨论,详见本系列博客的第
28
篇,《
字符串的排列
》,这里不再赘述。
接下来就是写代码了。思路想清楚之后,编码并不是很难的事情。下面是一段参考代码:
int
g_number = 0;
void
EightQueen()
{
const
int
queens = 8;
int
ColumnIndex[queens];
for
(int
i = 0; i < queens; ++ i)
ColumnIndex[i] = i;
Permutation(ColumnIndex, queens, 0);
}
void
Permutation(int
ColumnIndex[], int
length, int
index)
{
if
(index == length)
{
if
(Check(ColumnIndex, length))
{
++ g_number;
PrintQueen(ColumnIndex, length);
}
}
else
{
for
(int
i = index; i < length; ++ i)
{
int
temp = ColumnIndex[i];
ColumnIndex[i] = ColumnIndex[index];
ColumnIndex[index] = temp;
Permutation(ColumnIndex, length, index + 1);
temp = ColumnIndex[index];
ColumnIndex[index] = ColumnIndex[i];
ColumnIndex[i] = temp;
}
}
}
bool
Check(int
ColumnIndex[], int
length)
{
for
(int
i = 0; i < length; ++ i)
{
for
(int
j = i + 1; j < length; ++ j)
{
if
((i - j == ColumnIndex[i] - ColumnIndex[j])
|| (j - i == ColumnIndex[i] - ColumnIndex[j]))
return
false
;
}
}
return
true
;
}
void
PrintQueen(int
ColumnIndex[], int
length)
{
printf("Solution %d/n"
, g_number);
for
(int
i = 0; i < length; ++i)
printf("%d/t"
, ColumnIndex[i]);
printf("/n"
);
}
出处 http://zhedahht.blog.163.com/
。
相关文章推荐
- 程序员面试题精选100题(58)-八皇后问题
- 程序员面试题精选100题(58)-八皇后问题
- 程序员面试题精选100题(58)-八皇后问题[算法]
- 程序员面试题精选100题(23)-跳台阶问题[算法]
- 程序员面试题精选100题(23)-跳台阶问题[算法]
- 程序员面试题精选100题(23)-跳台阶问题
- 程序员面试题精选100题(50)-树的子结构
- 程序员面试题精选100题(56)-C/C++/C#面试题(4)
- 程序员面试题精选100题(31)-从尾到头输出链表
- 程序员面试题精选100题(46)-对称子字符串的最大长度
- 程序员面试题精选100题(52)-C++面试题(1)
- 程序员面试题精选100题(04)-二元树中和为某一值的所有路径[数据结构] 分类: 剑指offer 2014-11-03 09:05 117人阅读 评论(0) 收藏
- 程序员面试题精选100题(22)-整数的二进制表示中1的个数
- 程序员面试题精选100题(08)-求1+2+...+n[C/C++/C#]
- 程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表[数据结构]
- 程序员面试题精选100题(11)-求二元查找树的镜像[数据结构]
- 程序员面试题精选100题(14)-圆圈中最后剩下的数字
- 面试经典之剑指offer--58--八皇后问题
- 程序员面试题精选100题(57)-O(n)时间的排序
- 程序员面试题精选100题(28)-字符串的排列