最详细动态规划解析——背包问题

动态规划的定义

要解决一个复杂的问题,可以考虑先解决其子问题。这便是典型的递归思想,比如最著名的斐波那契数列,讲递归必举的例子。

斐波纳契数列的定义如下:F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
用递归可以很快写出这样一个函数,咋一看真牛逼,几行代码就搞定了

int fib(int i)
{
    if(i <= 1)
    {
        return 0;
    }
    return fib(i - 1) + fib(i - 2);
}

将该函数的执行过程用图表示出来,就会发现fib4执行了一次,fib3执行了两次,fib2执行了三次,fib1计算了5次,重复的次数呈现爆发增长,接近与指数级。如果n取得足够大,暂且不说费时的问题,直接就会因为递归次数太多,函数堆栈溢出而程序奔溃。
image

那么很快就有人想到,用一个数组来保存曾经计算过的数据来避免重复计算。这种思想便是动态规划
我们来实现一下

#include <iostream>
#include <stdlib.h>
#include <vector>

using namespace std;

int fib(int n, vector<int>& vec);

int main(int argc, char** argv)
{
        if(argc != 2)
        {
                cout << "usage: ./a.out number" << endl;
        }
        int num = atoi(argv[1]);

        vector<int> vec(num + 1, -1);

        int ret = fib(num, vec);

        cout << "fib(" << argv[1] << ")" << " = " << ret << endl;
        return 0;
}

int fib(int n, vector<int>& vec)
{
        if(n <= 1)
        {
                return 1;
        }

        if(vec[n] == -1)
        {
                vec[n] = fib(n - 1, vec) + fib(n - 2, vec);
        }
        return vec[n];
}

当然,对于递归问题也可以转化为循环来解决。

#include <iostream>
#include <stdlib.h>

using namespace std;

int fib(int n);

int main(int argc, char** argv)
{
        if(argc != 2)
        {
                cout << "usage: ./a.out number" << endl;
        }

        int ret = f
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值