c++ - 在巨大的棋盘上解决骑士的巡回赛问题?

标签 c++ stack malloc overflow knights-tour

我找到了解决骑士之旅问题的代码。

例如,如果我想求解尺寸为 800x800 的电路板,我会收到以下错误: test.exe 中 0x00007FF6345D3778 抛出异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001、0x00000082140C3000)。 test.exe 中 0x00007FF6345D3778 处的未处理异常:0xC00000FD:堆栈溢出(参数:0x0000000000000001、0x00000082140C3000)。

我怎样才能避免这个错误?我应该如何更改 Board 类才能解决这么大的问题? 我希望能够写:例如 Board<800> b6。

附言。此代码适用于小型电路板。

非常感谢。

class Board
{
public:
    array<pair<int, int>, 8> moves;
    array<array<int, N>, N> data;

    Board()
    {
        moves[0] = make_pair(2, 1);
        moves[1] = make_pair(1, 2);
        moves[2] = make_pair(-1, 2);
        moves[3] = make_pair(-2, 1);
        moves[4] = make_pair(-2, -1);
        moves[5] = make_pair(-1, -2);
        moves[6] = make_pair(1, -2);
        moves[7] = make_pair(2, -1);
    }

    array<int, 8> sortMoves(int x, int y) const
    {
        array<tuple<int, int>, 8> counts;
        for (int i = 0; i < 8; ++i)
        {
            int dx = get<0>(moves[i]);
            int dy = get<1>(moves[i]);

            int c = 0;
            for (int j = 0; j < 8; ++j)
            {
                int x2 = x + dx + get<0>(moves[j]);
                int y2 = y + dy + get<1>(moves[j]);

                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N)
                    continue;
                if (data[y2][x2] != 0)
                    continue;

                c++;
            }

            counts[i] = make_tuple(c, i);
        }
        sort(counts.begin(), counts.end());
        array<int, 8> out;
        for (int i = 0; i < 8; ++i)
            out[i] = get<1>(counts[i]);
        return out;
    }

    void solve(string start)
    {
        for (int v = 0; v < N; ++v)
            for (int u = 0; u < N; ++u)
                data[v][u] = 0;

        int x0 = start[0] - 'a';
        int y0 = N - (start[1] - '0');
        data[y0][x0] = 1;

        array<tuple<int, int, int, array<int, 8>>, N*N> order;
        order[0] = make_tuple(x0, y0, 0, sortMoves(x0, y0));

        int n = 0;
        while (n < N*N - 1)
        {
            int x = get<0>(order[n]);
            int y = get<1>(order[n]);

            bool ok = false;
            for (int i = get<2>(order[n]); i < 8; ++i)
            {
                int dx = moves[get<3>(order[n])[i]].first;
                int dy = moves[get<3>(order[n])[i]].second;

                if (x + dx < 0 || x + dx >= N || y + dy < 0 || y + dy >= N)
                    continue;
                if (data[y + dy][x + dx] != 0)
                    continue;

                ++n;
                get<2>(order[n]) = i + 1;
                data[y + dy][x + dx] = n + 1;
                order[n] = make_tuple(x + dx, y + dy, 0, sortMoves(x + dx, y + dy));
                ok = true;
                break;
            }

            if (!ok) // Failed. Backtrack.
            {
                data[y][x] = 0;
                --n;
            }
        }
    }

    template<int N>
    friend ostream& operator<<(ostream &out, const Board<N> &b);
};

template<int N>
ostream& operator<<(ostream &out, const Board<N> &b)
{
    for (int v = 0; v < N; ++v)
    {
        for (int u = 0; u < N; ++u)
        {
            if (u != 0) out << ",";
            out << setw(3) << b.data[v][u];
        }
        out << endl;
    }
    return out;
}

int main{
Board<800> b2;
b2.solve("b5");
cout << b2 << endl;
return 0
}

最佳答案

array<array<int, N>, N> dataN 800 需要大约 2.5 MB 的内存。

Board<800> b2分配在堆栈上。

根据平台的不同,默认堆栈大小约为 2-8MB。看起来您在堆栈大小通常为 2MB 的 Windows 上。由于您的数组大于堆栈的大小,因此会出现堆栈溢出。

你需要分配Board在堆上。例如:

int main{
    auto b2 = std::make_unique<Board<800>>();
    b2->solve("b5");
    cout << *b2 << endl;
    return 0
}

solve您还分配的功能 order在堆栈上。为了在堆上分配它,应该将其更改为这样的内容:

auto orderPointer = std::make_unique<array<tuple<int, int, int, array<int, 8>>, N*N>>();
// dereference the pointer to make array indexes easier
auto& order = *orderPointer;

关于c++ - 在巨大的棋盘上解决骑士的巡回赛问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54171653/

相关文章:

c++ - 不知道参数 1 从 sf::Vector2i 到 const sf::Vector2i<float>& 的转换

c++ - _CrtCheckMemory 的可靠性如何?

arm - PUSH 和 POP 括号中的寄存器顺序

c++ - 段错误将引用作为函数参数传递

c - malloc 中的指针到指针段错误

c++ - C++ 中的非托管 DLL

c++ - C 字符串数组,用字符串文字初始化

c++ - 关于 std::stack push 段错误的问题

c - 在分配内存后初始化 C 数组

linux - malloc 钩子(Hook)文档中的 'Save underlying hooks' 是什么意思?