【问题标题】:Slide puzzle app, DFS幻灯片拼图应用程序,DFS
【发布时间】:2012-12-19 07:03:19
【问题描述】:

我在解决滑动谜题时遇到以下问题。我处于状态,我可以确定谜题是否可以解决。而且我已经创建了将空标题向左、向右、向上和向下移动的函数,如果可以移动,它们返回 2D 数组,否则返回 0。我将初始配置存储在二维数组中。

我选择了有限的 DFS 来解决这个问题。所以我需要创建类似树(或链表)结构的东西,我的初始配置将是根目录。然后它将有(2,3 或 4)个孩子,具体取决于零的位置。这些节点将包含带有下一个配置的 int **array(由函数返回:toLeft、toRight、toUp 和 toDown)。

所以我可以使用递归来创建下一个节点,直到有目标配置。然后我可以“返回”到根目录并打印出这些步骤。例如:
[5] 左
[7] 向上
...
结束

但是我在创建链表时遇到了问题。到目前为止,我只有:

typedef struct Node{
int **array;
struct Node *left;
struct Node *right;
struct Node *up;
struct Node *down;
}Node;

如何将节点添加到列表中,如何确定它是左、右、上、下? 谢谢。

编辑

所以根据建议(已删除)我编辑了我的代码并添加了新功能...

   typedef struct Node{
    int **array;
    struct Node *left;
    struct Node *right;
    struct Node *up;
    struct Node *down;
    struct Node *parent;
    }Node;

Node* newNode(Node *parent, int **array){
    Node* u;
    u = malloc(sizeof(Node));
    if (u == NULL){
    printf("OUT OF MEMORY!");
    /* Free memory here.*/
    exit(1);
    }
    u->array = array;
    u->down = NULL;
    u->right = NULL;
    u->up = NULL;
    u->left = NULL;
    u->parent = parent;
    return u;
}

void setLeftNode(Uzel *parent, Uzel *child) {
  parent->left = child;
    }
/* setRightNode,Up,Down...*/


int isLeftChild (Node *node){
    if (node->parent == null) {return 0;}
    else{
        if (node->parent->left == node){return 1;}
        else{return 0;}
    }
}
/*is Right,Up,Down...*/

我添加了根目录: Node* root = newNode(NULL, array);

所以我的问题是:
1. 我怎样才能创建另一个节点(使用递归和来自其父节点的数组(更改拼图配置))?
2. 如何调用setLeftNode、setRightNode等?

感谢您的宝贵时间。 :)

【问题讨论】:

  • 我已经用我的新代码编辑了帖子...。但我被困住了。此外,当我创建一个节点根..然后我尝试创建节点 n = newNode(root, array);它导致我的程序在启动后终止,没有任何错误,但它什么也不做。
  • 我再次编辑它,现在,newNode 工作......我希望。
  • 你确定你需要这棵树吗?为什么不只使用一堆数组状态呢? (即扩展每个可能的下一个状态并将其推入堆栈,然后弹出一个,扩展等,直到你用完或解决难题)

标签: c


【解决方案1】:

我同意 Spudd86。您不需要显式构建状态数组树。只有当前路径中的那些就足够了,并且可以在堆栈上的指针中保持。

大概像这样的东西应该可以工作:

int dfs(int **state, int depthLimit, const char **steps) {
    if (isFinalState(state))
        return 1;

    if (depthLimit <= 0)
        return 0;

    int *newState;

    if (tryMoveLeft(state, &newState)) {
        if (dfs(newState, depthLimit, steps + 1)) {
            steps[0] = "left";
            freeState(newState);
            return 1;
        } else {
            freeState(newState);
        }
    }

    // The same for right, up, down ...

    // If no of the previous returns was taken, then this branch isn't the right one
    return 0;
}

isFinalState() 应该在状态对应于已解决的谜题时返回,tryMoveLeft() 应该在向左移动有效时返回,如果是则返回新分配的状态,freeState() 应该释放状态数组。 输出将存储在数组步骤中,必须在开始搜索之前分配足够的大小。

这并不能完全回答你的问题,但我希望它对你有帮助:-D

【讨论】:

  • 我已经用这里写的伪代码实现了算法:docstoc.com/docs/28438033/The-8-Puzzle 但是,我仍然有无限循环的问题。 const DEPTHBOUND(DFS 的限制)的值是否有任何公式取决于拼图的大小?谢谢。
  • 好吧,我不知道任何公式。肯定会小于(n * n)!具有 n*n 个字段的拼图步骤,但该值太大,对您没有帮助。如果我在学校没记错的话,那么您应该使用有限的 dfs,从限制 0 开始,然后将限制增加一,直到找到有效的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
  • 2010-11-04
相关资源
最近更新 更多