【问题标题】:Memoization with Ackermann function C++使用 Ackermann 函数 C++ 进行记忆
【发布时间】:2018-02-11 20:39:50
【问题描述】:

好的,这是一个家庭作业,所以请尽量指导我而不给我直接的答案。 我正在尝试使用 Ackermann 函数(C++)进行记忆。当达到 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;
}

所以下面是我的新方法。但我不知道为什么我不能在我的acker 函数中使用memoMap.insert(make_pair(m, n), (acker(m - 1, 1)));??

#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;
}

【问题讨论】:

  • 在OCaml中做作业是不是太晚了?
  • 必须在 C++ 中完成。

标签: c++ memoization ackermann


【解决方案1】:

函数的记忆需要记住整个参数元组以前是否见过。使用由单个整数索引的数组不会解决这个问题:有两个参数!您可以使用二维数组,一维用于 m,另一维用于 n。这对于只有小参数的函数很实用。因此,二维数组可能很小并且仍然涵盖感兴趣的情况。你可以做一些阅读和实验来确定阿克曼是否符合这个标准。不过,一般来说,您会希望使用从 (m,n) 对到结果的映射。 C++ 映射是一个很好的学习数据结构,所以我建议你在这里尝试一下。除非你被难住了,否则我不会提供代码。学习如何从文档和可用示例中了解如何使用库比获得解决问题的代码要好得多。

【讨论】:

  • 谢谢。我会玩一点。我越看我发布的代码,就越能发现我的逻辑在不止一个领域存在缺陷。
【解决方案2】:

map.insert() 需要一对。该对应该是一对整数(对于 m,n)和一个整数(对于 Ack func 值)。

因此,它将如下:

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 时,代码块似乎没有表格记录和/或查找。

【讨论】:

  • 感谢您的意见!我提交的作业迟到且不完整,但我仍想在本周重新审视它并使其发挥作用以供理解。
猜你喜欢
  • 2012-09-20
  • 2016-02-11
  • 2022-11-03
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 2018-01-05
相关资源
最近更新 更多