我编写了尝试解决传教士和食人族问题的代码,并实现了Node来将信息保存在Node::arrNode::parent中。这些由函数bfs返回时,将以最短路径给出状态。

bfs返回时,它具有正确的parents编号。但是,当我在Visual Studio调试器中检查Node last时,我注意到它的parents.arr包含垃圾,即arr[0]=-858993460。但是Node last具有正确的arr(问题{0,0,1,3,3,0}的最终状态)。这些信息如何丢失?

节点

#pragma once
#include <array>
class Node {
public:
    std::array<int, 6> arr;
    Node *parent;
    Node(std::array<int, 6> arr, Node *parent = NULL);
    Node();
};


node.cpp

#include "Node.h"

Node::Node(std::array<int, 6> arr, Node *parent) : arr(arr), parent(parent) {};
Node::Node(): parent(NULL) {};


main.cpp

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) {
  array<int, 6> arr = current_node.arr;
    array<int, 3> left, right;
    // apply valid moves to arr
    // copy the arr to left and right and check if the move applied are valid
    // if valid and no duplicates in the queue do proceed to the next lines below
    Node n = Node(arr, &current_node);
    q.push(n);

}

Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) {
    while (!q.empty()) {
        Node current = q.front();
        q.pop();

        if (achievedGoal(current.arr) == 1) {
            return current;
        }
        for (const auto& move : moves) {
            applyMoves(q, current, move);
        }
    }
    Node n;
    return n;
}

int main() {
    array<int, 6> init_state{ 3,3,1,0,0,0 };
    array<array<int, 3>, 5> moves{ { {1,0,1}, {0,1,1}, {1,1,1}, {2,0,1}, {0,2,1} } };
    Node n = Node(init_state);
    queue<Node> q;
    q.push(n);
    Node last = bfs(q, moves);
}

最佳答案

我相信问题出在

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) {
  array<int, 6> arr = current_node.arr;
    array<int, 3> left, right;
    // apply valid moves to arr
    // copy the arr to left and right and check if the move applied are valid
    // if valid and no duplicates in the queue do line 31 and 32
    Node n = Node(arr, &current_node);
    q.push(n);

}


current_node是副本,您正在存储它的地址。函数结束时,该副本被销毁,现在您有了一个悬空的指针。您应该可以通过引用current_node来修复它。

编辑:

您在

Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) {
    while (!q.empty()) {
        Node current = q.front();
        q.pop();

        if (achievedGoal(current.arr) == 1) {
            return current;
        }
        for (const auto& move : moves) {
            applyMoves(q, current, move);
        }
    }
    Node n;
    return n;
}


在这里,创建current这是一个本地自动对象,然后将队列的前端复制到其中,然后从队列中获得pop()前端。因此,当将此节点用作父节点时,一切都很好,直到您移至while循环的下一个迭代。一旦执行此操作,current就被破坏了,这意味着指向它的所有内容现在都在晃来晃去。然后循环开始备份并创建一个新的current。如果此对象是在我认为是的示例位置中创建的,那么您创建的所有节点的父节点现在都指向该新节点。

他们目前正在执行的操作将无法正常工作。我不太确定如何更改它才能获得正确的行为。

10-08 11:38