【发布时间】:2015-10-16 20:47:35
【问题描述】:
我有以下问题:这个游戏的目标是从棋盘上移除除一个之外的所有钉子。完美的游戏只在中心位置留下一个钉子(黑色的)。基本上,通过用另一个钉子跳过每个钉子来移除钉子。只有在钉子的另一边有空位并且我就在钉子前面时,我才能跳过钉子。
我正在尝试理解以下递归函数,该函数试图使用深度优先搜索来解决问题。虽然我有点熟悉这个问题在正常情况下是如何工作的,这意味着当我需要移除钉子时。当我最终处于无法消除挂钩的情况下,我无法很好地掌握递归步骤,在接下来的步骤中,我不得不提出旧的消除挂钩(回溯),以便我会发现解决方案的另一条途径。这似乎消耗了大量的执行时间。
函数的一般流程是:
- 使用嵌套的 for 循环遍历电路板。
- 如果满足以下条件,则找到要移动的钉子:
- 在左上或右下有一个直接相邻的。
- 卸下要卸下的挂钩后,有一个空闲的地方可以移动。
- 如果所有这些条件都为真,我们将更改挂钩的状态
- 如果无法再移动钉子,请恢复之前的电路板配置并寻找其他路径。
这里是预处理器指令:
#include <stdio.h>
#define N 11
/****** Accepted or unaccepted solution ******/
#define YES 1
#define NO 0
/****** Representation of the board ******/
/* 0 - the position is free: no peg is in the position
1 - a peg is in the postion
2 - an obstacle is in the position (not part of the board) */
#define OCCUPIED 1
#define FREE 0
#define WALL 2
/****** Stack size ******/
#define MAXST 5000
typedef char boolean;
/****** Directions where to move *****/
enum dir{NORTH,EAST,SOUTH,WEST};
/****** Directions horizentally ******/
int dx[]={0, 1,0,-1};
/****** Directions Vertically ******/
int dy[]={-1,0,1, 0};
/****** Board Representation ******/
char b[N][N]={
{2, 2,2,2,2,2,2,2,2,2, 2},
{2, 2,2,2,1,0,0,2,2,2, 2},
{2, 2,2,2,0,0,1,2,2,2, 2},
{2, 2,2,2,0,0,0,2,2,2, 2},
{2, 0,0,1,0,0,0,1,1,1, 2},
{2, 0,0,0,0,0,0,0,0,0, 2},
{2, 0,1,0,0,1,0,0,0,0, 2},
{2, 2,2,2,1,0,0,2,2,2, 2},
{2, 2,2,2,0,0,0,2,2,2, 2},
{2, 2,2,2,1,0,0,2,2,2, 2},
{2, 2,2,2,2,2,2,2,2,2, 2}
};
这是负责寻找解决方案的函数:
/****** move finds the next move to perform in order to advance in the search ******/
boolean move(int pegs){
/****** x - the x position of the peg examined on the board
y - the y position of the peg examined on the board
xnear - the x position of the adjascent peg to be removed
ynear - the y position of the adjascent peg to be removed
xnew - the new x position of the peg that expelled the removed previous peg
ynew - the new x position of the peg that expelled the removed previous peg ****/
int x,y,xnear,ynear,xnew,ynew;
enum dir d;
/* Base case 1: solution = one peg left on the whole board */
/* if(pegs==1){
return(YES);
} */
/* Base case 2: solution = one peg at the center of the board (5,5) */
if(pegs==1) {
if (b[5][5]==OCCUPIED)
return(YES);
else return(NO);
}
/*Scanning the board from top to bottom, left to right*/
for(x=0;x<N;x++)
for(y=0;y<N;y++)
/* In order for the move to occur you need to 1. have a peg in a position */
if(b[y][x] == OCCUPIED){
/**************/
/* Finding adjascent pegs to remove from the board */
for(d=NORTH;d<=WEST;d++){
xnear=x+dx[d];
ynear=y+dy[d];
/*****************/
/* 2. Have another peg adjascent to the peg making the move */
if(b[ynear][xnear]== OCCUPIED){
xnew=xnear+dx[d];
ynew=ynear+dy[d];
/****************/
/* 3. Have the position where the peg will be moving empty */
if(b[ynew][xnew]==FREE){
b[y][x]=FREE; /* do move */
b[ynear][xnear]=FREE;
b[ynew][xnew]=OCCUPIED;
pegs--;
print_board(b);
push(b,x,y,d); // Pushing the action to a stack
if(move(pegs)){
return(YES);
}
b[y][x]=OCCUPIED; /* undo move */
b[ynear][xnear]=OCCUPIED;
b[ynew][xnew]=FREE;
pegs++;
pop();
}
}
}
}
return(NO);
}
我的问题是:
-
boolean move(int pegs)函数的递归部分如何在代码中工作,它如何跟踪已经扩展的导致死胡同的案例? 我的猜测是在boolean move(int pegs)函数中,并且准确地说:if(move(pegs)){ return(YES); } b[y][x]=OCCUPIED; /* undo move */ b[ynear][xnear]=OCCUPIED; b[ynew][xnew]=FREE; print_board(b); pegs++; pop(); 执行时间过长才能找到解决方案(很多小时但仍未找到解决方案)是否正常?有没有办法提高执行时间?
【问题讨论】:
标签: c search recursion artificial-intelligence depth-first-search