过去几天我花了很多时间试图绕过递归的回溯。从概念上讲,我认为我理解它,但我似乎无法实现它,而不是像n-queen这样的事情。挑战是通过填写以A开头并以Y结尾的字母来解决5x5拼图。每个字母必须与其前后的字母相邻(对角线计为相邻字母)。
此外,围绕拼图的边缘是"线索"定义后续字母必须与"游戏板的最外边缘相关的位置"原样。例如,字母B必须水平或垂直出现" B"在董事会的线索部分,而字母" P"将出现在" P"对角线上。在董事会的线索部分,因为" P"在一个角落里。我目前把电路板作为一个7x7阵列布局,其中包括外部的线索,以保持组织如下。
T X Y N F E J
V 0 0 0 0 0 O
R 0 0 0 0 0 Q
L 0 0 0 0 0 C
K 0 0 0 0 0 H
G 0 0 0 0 0 I
P W U S D B M
" A"可以出现在棋盘内的任何地方(标有0' s的区域)。我从A开始在阵列[3] [5]开始尝试从那里填充其余的游戏板。我设法在它停止工作之前写入字母F,所以我的电路板目前看起来像这样。
T X Y N F E J
V 0 0 0 F E O
R 0 0 0 D B Q
L 0 0 0 C A C
K 0 0 0 0 0 H
G 0 0 0 0 0 I
P W U S D B M
以下是目前的模式代码。我目前正在使用字符堆栈来保存所有字母(顶部为B,底部为Y):
public boolean solver(int currRow, int currCol){ //sets current focus
nt column=0;
int row=0;
if(abcs.empty()) //the base case, returns true when abc stack is empty
return true;
for(row=currRow-1;row<=(currRow+1);row++) //cycles through the spaces
//adjacent to the focus spot
{
for(column=currCol-1;column<=(currCol+1);column++)
{
if(promising(row,column,abcs.peek())) //invokes a method
{ // designed to check the clues
prevChar=array[row][column]; //saves char just in case
array[row][column]=abcs.pop(); //pops stack and adds to board
solver(row,column); //my attempt at recursion
}
else //haven't quite figured out what needs to be here
;
}
}
display();
abcs.push(prevChar); //these steps are for replacing the array
//values if no legit adjacent spots are found
if(array[currRow][currCol]!='A') //(unsure if necessary)
array[currRow][currCol]='0';
return(false);} //the false return that is supposed to begin
//backtracking
public void display() //prints the 2d array in a grid
{
String holder="";
for(int i = 0; i<7;i++)
{
for(int k = 0; k<7; k++)
{
holder=holder + array[i][k] + " ";
}
holder=holder + "\n";
}
System.out.println(holder);
}
我研究过回溯,似乎这个问题介于一般的迷宫遍历&#34;和&#34;数独&#34;。似乎有必要存储我之前访问过的网格的哪些部分,但是我还不确定哪种方法最适合它,同时仍然认为这是递归。我很容易被告知,你已经以完全错误的方式解决了这个问题,因为我老实说不知道还有什么可以尝试。任何建议将不胜感激。
答案 0 :(得分:1)
基本上,回溯的工作原理如下:
-Pick a starting point
-While the problem isn't solved
-For each path from the starting point
-Set that as the starting point and recurse
-If it returns true, then return true
-Undo the current move (since none of the options panned out)
-Return false
我无法清楚地知道你“撤消”的位置?您可以通过在每次移动时将状态推送到堆栈并在撤消时弹出它,或者通过撤消板上的移动来实现此操作。
我会重新开始尝试使Java代码模仿上面的算法。另外,我会向它介绍更多面向对象的代码。
您可以实施isSolved()
,getValidMoves()
和主要方法doNextMove()
等方法,这些方法将被称为递归调用。
如果我必须实现这个,我会创建类似于包含状态的Board
类。
Board
类可以使用getValidMoves()
,isSolved()
和doMove()
方法。
你的BackTracker
类应该实现递归逻辑,看起来像这样。
public static void iterate(Board b, char c)
{
List<Move> moves = b.getValidMoves(c);
for (Move m : moves)
{
Board n = Board.copyOf(b);
n.doMove(m, c);
if (n.isSolved())
{
System.out.println(n.toString());
}
else
{
iterate(n, (char) (c+1));
}
}
}
public static void main(String[] args) {
Board b = Board.create();
iterate(b, 'a');
}
顺便说一下。我有3个解决方案。 (在7296次迭代中)