当为n-
Queen问题的所有可能解决方案实现算法时,我发现许多分支机构都可以达到相同的解决方案。有什么好的方法可以生成解决n皇后问题的每一个独特的解决方案?如何避免由不同分支机构(存储和比较除外)生成的重复解决方案?
这是我尝试的第一个解决方案:http :
//www.ideone.com/hDpr3
码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* crude */
#define QUEEN 'Q'
#define BLANK '.'
int is_valid (char **board, int n, int a, int b)
{
int i, j;
for (i=0; i<n; i++)
{
if (board[a][i] == QUEEN)
return 0;
if (board[i][b] == QUEEN)
return 0;
}
for (i=a, j=b; (i>=0) && (j>=0); i--, j--)
{
if (board[i][j] == QUEEN)
return 0;
}
for (i=a, j=b; (i<n) && (j<n); i++, j++)
{
if (board[i][j] == QUEEN)
return 0;
}
for (i=a, j=b; (i>=0) && (j<n); i--, j++)
{
if (board[i][j] == QUEEN)
return 0;
}
for (i=a, j=b; (i<n) && (j>=0); i++, j--)
{
if (board[i][j] == QUEEN)
return 0;
}
return 1;
}
void show_board (char **board, int n)
{
int i, j;
for (i=0; i<n; i++)
{
printf ("\n");
for (j=0; j<n; j++)
{
printf (" %c", board[i][j]);
}
}
}
int nqdfs_all (char **board, int n, int d)
{
int i, j, ret = 0;
/* the last queen was placed on the last depth
* therefore this dfs branch in the recursion
* tree is a solution, return 1
*/
if (d == n)
{
/* Print whenever we find one solution */
printf ("\n");
show_board (board, n);
return 1;
}
/* check all position */
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
if (is_valid (board, n, i, j))
{
board[i][j] = QUEEN;
nqdfs_all (board, n, d + 1);
board[i][j] = BLANK;
}
}
}
return ret;
}
int nqdfs_first (char **board, int n, int d)
{
int i, j, ret = 0;
/* the last queen was placed on the last depth
* therefore this dfs branch in the recursion
* tree is a solution, return 1
*/
if (d == n)
return 1;
/* check all position */
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
if (is_valid (board, n, i, j))
{
board[i][j] = QUEEN;
ret = nqdfs_first (board, n, d + 1);
if (ret)
{
/* if the first branch is found, tell about its
* success to its parent, we will not look in other
* solutions in this function.
*/
return ret;
}
else
{
/* this was not a successful path, so replace the
* queen with a blank, and prepare board for next
* pass
*/
board[i][j] = BLANK;
}
}
}
}
return ret;
}
int main (void)
{
char **board;
int n, i, j, ret;
printf ("\nEnter \"n\": ");
scanf ("%d", &n);
board = malloc (sizeof (char *) * n);
for (i=0; i<n; i++)
{
board[i] = malloc (sizeof (char) * n);
memset (board[i], BLANK, n * sizeof (char));
}
nqdfs_first (board, n, 0);
show_board (board, n);
printf ("\n");
return 0;
}
为了生成所有可能的解决方案,我使用了相同的代码nqdfs_all ()
功能,但没有将控件返回给父级,而是继续枚举和检查。对该函数的调用将显示不同分支获得的重复结果。
您应该利用每个皇后必须放在不同列中的事实。如果已经在前k列中放置了k个皇后,则将第k + 1个皇后号递归地放置在k +
1列中,并遍历第1到n行(而不是像现在那样遍历所有n * n个单元格)。为每个有效的位置继续k:= k +
1。这将避免任何重复的结果,因为该算法根本不会生成任何重复的板。
编辑:您如何避免对称性的问题:可以预先避免的一部分,例如,通过在列1到行1限制女王1,…
n/2
。如果要完全避免对称解决方案的输出,则必须将找到的每个解决方案存储在列表中,每当找到新解决方案时,在打印出来之前,请测试列表中是否已存在对称解决方案之一。
为了提高效率,您可以使用每个板的“规范代表”,定义如下。生成给定板的所有对称板,将每块对称板包装到一个字节数组中,并保留其中的数组,该数组被解释为一个大数字,具有最小值。这种打包的表示形式是每个板对称类的唯一标识符,可以轻松地放入字典/哈希表中,这使测试该对称类是否已经非常有效。
主要内容:回溯算法解决N皇后问题N 皇后问题源自国际象棋,所有棋子中权力最大的称为皇后,它可以直着走、横着走、斜着走(沿 45 度角),可以攻击移动途中遇到的任何棋子。N 皇后问题的具体内容是:如何将 N 个皇后摆放在 N*N 的棋盘中,使它们无法相互攻击。 举个简单的例子,将 4 个皇后摆放在 4*4 的棋盘中,下图给出了一种摆放方式,各个皇后无论是直着走、横着走还是斜着走,都无法相互攻击。 图 1 N 皇后问题 Q 表示放置
问题描述 这道题是 LeetCode 51题。 将 $n$ 个皇后放置在 $n×n$ 的棋盘上,并且使皇后彼此之间不能相互攻击。即同一行、同一列、同一对角线只能有一个皇后。 思路简述 N 皇后问题是回溯法的一个经典案例。回溯法是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。当探索到某一步,发现原先选择并不优或达不到目标时,就退回一步重新选择。 回溯法通常采用递归实现。对本题而言,搜
问题内容: 在不求助于蛮力技术或任何需要STL的情况下,计算n个可能元素的所有可能的length-r组合的最快方法是什么? 在为数据结构课程中的最终项目开发Apriori算法时,我开发了一个有趣的解决方案,该解决方案使用了移位和递归,下面将向有 兴趣的人分享一下答案。但是,这是实现此目标的最快方法(不使用任何公共库)吗? 出于好奇,我提出的要求更多,因为我目前拥有的算法可以很好地满足我的目的。 问
问题内容: 我需要迭代计算排列。方法签名如下所示: 为了n = 3例如,返回值将是: 您将如何以最有效的方式迭代进行此操作?我可以递归执行此操作,但是我有兴趣看到许多其他迭代执行方法。 问题答案: 请参阅QuickPerm算法,它是迭代的:http ://www.quickperm.org/ 编辑: 为了清楚起见,在Ruby中进行了重写:
本文向大家介绍C#用递归算法解决八皇后问题,包括了C#用递归算法解决八皇后问题的使用技巧和注意事项,需要的朋友参考一下 1.引子 中国有一句古话,叫做“不撞南墙不回头",生动的说明了一个人的固执,有点贬义,但是在软件编程中,这种思路确是一种解决问题最简单的算法,它通过一种类似于蛮干的思路,一步一步地往前走,每走一步都更靠近目标结果一些,直到遇到障碍物,我们才考虑往回走。然后再继续尝试向前。通过
我正在编写一个python类来寻找8皇后问题的解决方案。如何在方法中正确实现回溯?我认为递归应该可以工作,但是,程序在第一次尝试没有找到解决方案后停止,回溯也不会发生。所有helper方法都能正常工作。 我的问题是在添加女王之前缺少一个板子的深度副本,还是仅仅是缺少回溯?
注意:我目前不检查是否一个瓷砖被占用,我想采取这一步一次,第一步是得到正确的结果,哪些瓷砖的角色可以去。 我有一个板大小的3D阵列。第三个维度有两个层,第一个被初始化为所有99,除了你正在移动的字符(原点),它被设置为0。此维度包含从每个瓷砖到原点的距离。另一层包含到达该瓷砖所需的对角线数。 基本上,我有一个递归函数,它检查每个相邻的瓷砖到原点的最低距离,并将当前瓷砖设置为最低距离数+1(如果是第
这个问题可能没有具体说明,但我认为很重要。当您想要解决一个优化问题而又不太熟悉方法时,首先想到的是它。 我可以举一些简单的例子: 获取列表的min元素(非常简单) 列出集合的所有置换 列出集合的所有子集 这些问题都有成熟的解决方法。但也有问题不是很清楚: 列出两个字符串的所有(我指的不是编辑操作中最短的一个) 列出两个序列的所有 列出括号的所有可能性 我不知道用蛮力法解决这些问题。我的问题是: 是