c++ - Solving knight's tour problem on a huge board?
问题描述
I have found this code that solves the Knight's Tour problem.
If I, for example, want to solve a board of size 800x800 I get the following error: Exception thrown at 0x00007FF6345D3778 in test.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x00000082140C3000). Unhandled exception at 0x00007FF6345D3778 in test.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x00000082140C3000).
How can I avoid this error? How should I change the Board class such that it can solve a board this big? I want to be able to write: Board<800> b6 for example.
PS. This code works for small boards.
Thank you very much.
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> data
with N
being 800 requires around 2.5 MB of memory.
Board<800> b2
is allocated on the stack.
Depending on the platform the default stack size is around 2-8MB. It looks like you are on windows where the stack size is usually 2MB. As your array is larger than the size of the stack you get a stack overflow.
You need to allocate Board
on the heap. e.g.:
int main{
auto b2 = std::make_unique<Board<800>>();
b2->solve("b5");
cout << *b2 << endl;
return 0
}
In the solve
function you are also allocating order
on the stack. This should be changed to something like this in order to allocate it on the heap:
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;
推荐阅读
- android - 原因:org.koin.core.error.InstanceCreationException:无法为 [type:Factory,primary_type 创建实例
- microsoft-teams - 我想知道向我的团队机器人发送消息的当前用户的时区
- mysql - MYSQL,显示 DML 语句并按 desc 出现对其进行排序
- php - 动态 HTML 图像链接从 PHP 中的数据库中提取错误信息
- javascript - django AdminDateWidget: Uncaught ReferenceError: quickElement is not defined
- java - 使用 JSch 获取远程 bash shell 但自动完成功能不起作用
- java - 在 Java 中通过控制台编辑给定的字符串
- google-maps - Flutter Maps:如何更改标记点击上的标记图标
- string - 如果包含特定字符串,则阻止 URL
- java - 在 Lucene 中使用 CharTermAttribute 显示整行