好的,这是一个家庭作业,所以请尽量指导我,不要给我直接的答案。
我试图用Ackermann函数(C ++)进行memoization。当达到Ackermann时,它没有达到我的预期(1,2)。有什么东西告诉我,我应该尝试为记忆制作一个map
而不是array
?任何意见都表示赞赏。
#include <iostream>
using namespace std;
static int ackerMemoization[1000];
int acker(int m, int n)
{
if (m == 0)
return n + 1;
if (n == 0)
return acker(m - 1, 1);
if (ackerMemoization[m] != 0)
return ackerMemoization[m - 1];
else
{
ackerMemoization[m] = acker(m - 1, acker(m, n - 1));
return ackerMemoization[m];
//return acker(m - 1, acker(m, n - 1));
}
}
int main()
{
for (int i = 0; i < 1000; i++)
{
ackerMemoization[i] = 0;
}
//cout << "Ackermann(3, 20) = " << acker(3, 20) << endl;
//cout << "Ackermann(4, 0) = " << acker(4, 0) << endl;
//cout << "Ackermann(4, 1) = " << acker(4, 1) << endl;
for (int m = 0; m <= 4; ++m)
{
for (int n = 0; n < 20; ++n)
{
cout << "Ackermann(" << m << ", " << n << ") = " << acker(m, n) << "\n";
}
}
cin.get();
return 0;
}
以下是我的新方法。但我无法弄清楚为什么我无法在memoMap.insert(make_pair(m, n), (acker(m - 1, 1)));
函数中使用acker
?
#include <iostream>
#include <map>
using namespace std;
static map<pair<int, int>, int> memoMap;
int acker(int m, int n)
{
if (m == 0)
return n + 1;
if (n == 0)
{
//memoMap.emplace[make_pair(m, n), (acker(m - 1, 1)];
memoMap.insert(make_pair(m, n), (acker(m - 1, 1)));
return acker(m - 1, 1);
}
else
{
return acker(m - 1, acker(m, n - 1));
}
}
int main()
{
//static map<pair<int, int>, int> memoMap;
//cout << "Ackermann(3, 20) = " << acker(3, 20) << endl;
//cout << "Ackermann(4, 0) = " << acker(4, 0) << endl;
//cout << "Ackermann(4, 1) = " << acker(4, 1) << endl;
for (int n = 0; n <= 20; ++n)
{
cout << "Ackermann(" << 0 << ", " << n << ") = " << acker(0, n) << endl;
}
cout << endl;
for (int n = 1; n <= 20; ++n)
{
cout << "Ackermann(" << 1 << ", " << n << ") = " << acker(1, n) << endl;
}
cout << endl;
for (int n = 2; n <= 20; ++n)
{
cout << "Ackermann(" << 2 << ", " << n << ") = " << acker(2, n) << endl;
}
cout << endl;
for (int n = 3; n <= 20; ++n)
{
cout << "Ackermann(" << 3 << ", " << n << ") = " << acker(3, n) << endl;
}
cout << endl;
for (int n = 4; n <= 2; ++n)
{
cout << "Ackermann(" << 4 << ", " << n << ") = " << acker(4, n) << endl;
}
cin.get();
return 0;
}
答案 0 :(得分:1)
函数的记忆需要记住以前是否已经看过整个参数元组。使用由单个整数索引的数组不会对此问题执行此操作:有两个参数!你可以使用一个二维数组,一个维度为m,另一个维度为n。这对于只有小参数的函数很实用。因此,2d阵列可能很小并且仍然覆盖感兴趣的情况。您可以进行一些阅读和实验,以确定Ackerman是否符合此标准。但是,一般情况下,您需要使用从(m,n)对到结果的映射。 C ++地图是一个很好的数据结构,所以我建议你在这里试试。除非你难过,否则我不会提供代码。学习如何使用文档和可用示例中的库比获得解决问题的代码要好得多。
答案 1 :(得分:0)
map.insert()需要一对。该对应该是一对整数(对于m,n)和一个整数(对于Ack函数值)。
因此,它将如下:
auto key = make_pair(m, n);
auto value = acker(m-1, 1);
memoMap.insert(make_pair(key, value));
如果您使用的是c ++ 03或更早的标准,则auto可能无法正常工作。他们应该是:
pair<int, int> key = make_pair(m, n);
int value = acker(m-1, 1);
我认为你正在路上。我想知道为什么在计算非平凡的情况之前你没有查找memoMap。例如。 acker(m-1,n)可能会多次计算。此外,当mn!= 0时,代码块似乎没有表记录和/或查找。