我在动态编程方面有点困难。更具体地说,实现了一个查找斐波那契数n的算法。
我有一个很简单的算法:
int fib(int n) {
if(n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
字符串
但是当我尝试使用memoization时,函数总是返回0:
int fib_mem(int n) {
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
型
我已经定义了lookup_table,并在所有元素中初始存储了NIL。
有什么可能出问题吗?
以下是整个程序的要求:
#include <iostream>
#define NIL -1
#define MAX 100
long int lookup_table[MAX];
using namespace std;
int fib(int n);
int fib_mem(int n);
void initialize() {
for(int i = 0; i < MAX; i++) {
lookup_table[i] == NIL;
}
}
int main() {
int n;
long int fibonnaci, fibonacci_mem;
cin >> n;
// naive solution
fibonnaci = fib(n);
// memoized solution
initialize();
fibonacci_mem = fib_mem(n);
cout << fibonnaci << endl << fibonacci_mem << endl;
return 0;
}
int fib(int n) {
if(n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
int fib_mem(int n) {
if(lookup_table[n] == NIL) {
if(n <= 1)
lookup_table[n] = n;
else
lookup_table[n] = fib_mem(n-1) + fib_mem(n-2);
}
return lookup_table[n];
}
型
7条答案
按热度按时间xt0899hw1#
我倾向于通过将朴素实现与记忆化混合来找到编写记忆化的最简单方法:
字符串
zqdjd7g92#
字符串
使用完全相同的功能,这是工作正常。
您在初始化
lookup_table
时做错了一些事情。8gsdolmq3#
由于问题是初始化,C++标准库允许您初始化序列,而无需编写
for
循环,从而防止您犯错误,例如使用==
而不是=
。std::fill_n函数的作用是:
字符串
gajydyqb4#
有趣的概念。通过记忆加速。
还有一个不同的概念,你可以称之为编译时记忆,但实际上它是编译时预先计算所有适合64位值的斐波那契数。
斐波那契数列的一个重要属性是其值会以指数形式增长,因此,所有现有的整型数据类型都会很快溢出。
用比奈的公式,你可以计算出第93个斐波那契数是最后一个适合64位无符号值的数。
在编译期间计算93个值是一个非常简单的任务。
我们首先将计算斐波那契数的默认方法定义为
constexpr
函数:字符串
有了这个,斐波那契数可以很容易地在运行时计算。然后,我们用所有的斐波那契数填充
std::array
。我们还使用constexpr
,并使其成为一个带有可变参数包的模板。我们使用
std::integer_sequence
为索引0,1,2,3,4,5,.创建一个斐波那契数。这很简单,也不复杂:
型
这个函数将被输入一个整数序列0,1,2,3,4,.并返回一个
std::array<unsigned long long, ...>
和相应的斐波那契数。我们知道我们最多可以存储93个值。因此我们创建了下一个函数,它将调用上面的整数序列1,2,3,4,.,92,93,如下所示:
型
现在,终于,
型
将给予我们一个编译时的
std::array<unsigned long long, 93>
,名为FIB,包含所有的Fibonacci数。如果我们需要第i个Fibonacci数,那么我们可以简单地写FIB[i]
。在运行时不会有计算。我不认为有更快的方法来计算第n个斐波那契数。
请参阅下面的完整程序:
型
使用Microsoft Visual Studio Community 2019版本16.8.2开发和测试。
另外还使用clang11.0和gcc10.2进行了编译和测试
语言:C++17
cdmah0mi5#
在
initialize()
函数中有一个错误:字符串
在所指的行中,您比较
lookup_table[i]
和NIL
(并且不使用结果),而不是将NIL
分配给lookup_table[i]
。对于赋值,应该使用
=
而不是==
。此外,在这种情况下,最正确的做法是编译程序时启用所有警告。例如,MS VC++显示以下警告:
型
3htmauhk6#
这个错误出现在初始化函数上(你使用了比较运算符'==',而你想要一个属性运算符'=')。但是,在语义上,你不需要用-1(NIL)初始化look_table,因为Fibonacci的结果永远不会是0(零);所以,你可以用零初始化它。看看下面的最终解决方案:
字符串
iqxoj9l97#
在我的解决方案中,我使用一个map而不是数组来存储memo。
字符串