添加记忆-动态规划

Adding Memoization - Dynamic Programming

本文关键字:动态规划 记忆 添加      更新时间:2023-10-16

我目前正在练习一些动态规划,我遇到了马戏团塔问题。
我用动态规划解决了这个问题,并使用递归实现了它。我用很少的输入测试了它,它似乎工作得很好。

现在,我已经挣扎了几个小时,试图找出如何在我的解决方案中添加记忆。

  1. 我如何在我的解决方案中添加工作备忘录?我的错误在哪里?
  2. 对于如何添加记忆,是否有任何经验法则或指导方针?

马戏团塔问题:一个马戏团正在设计一座人们站在彼此肩膀上的塔。每个人都必须比他下面的人既矮又轻。给定马戏团中每个人的身高和体重,写一个方法来计算这样一个塔中可能的最大人数。

My Solution &代码
动态编程

OPT[N,P] = highest tower with N given persons and person P is at the top
----------------------------------------------------------
OPT[0,P]                                = 0
OPT[i,P] where person i can be above P  = max(OPT[i-1,i]+1,OPT[i-1,P])
OPT[i,P] else                           = OPT[i-1,P]
代码:

struct Person{
    int ht;
    int wt;
};
// Without Memoization
int circusTower(int n, Person* top, std::vector<Person>& persons){
    if (n == 0)
        return 0;
    if (top == NULL || top->ht > persons[n - 1].ht && top->wt > persons[n - 1].wt)
        return max(circusTower(n - 1, &persons[n - 1], persons) + 1, circusTower(n - 1, top, persons));
    else
        return circusTower(n - 1, top, persons);
}
// With Memoization
int circusTower(int n, Person* top, std::vector<Person>& persons, std::vector<int>& memo){
    if (n == 0)
        return 0;
    int result;
    if (memo[n-1] == 0) {
        if (top == NULL || top->ht > persons[n - 1].ht && top->wt > persons[n - 1].wt)
            result = max(circusTower(n - 1, &persons[n - 1], persons, memo) + 1,
                         circusTower(n - 1, top, persons, memo));
        else
            result = circusTower(n - 1, top, persons, memo);
        memo[n - 1] = result;
        return result;
    } else {
        return memo[n-1];
    }
}

Main - test:

int main(){
    std::vector<Person> persons = { {65, 100},{100, 150},{56, 90}, {75, 190}, {60, 95},{68, 110} };
    std::stable_sort(persons.begin(), persons.end(), sortByWt);
    std::stable_sort(persons.begin(), persons.end(), sortByHt);
    std::vector<int> memo(6,0);
    //Without memoization
    cout << circusTower(6, NULL, persons) << endl;
    //With memoization
    cout << circusTower(6, NULL, persons, memo) << endl;
}

在上面main中的例子中,正确的结果是5。我的常规解决方案(没有记忆)打印5,但有了记忆,它打印6。

你的方法依赖于3个参数但是你只能记住第一个参数n

事实上,在你的情况下,第三个(persons)是常数,但第二个(top)在递归调用过程中发生变化。

所以由于你的记忆,下面两个都错误地返回了相同的值:

  • circusTower(n - 1, &persons[n - 1], persons, memo)
  • circusTower(n - 1, top, persons, memo)