[动态规划与回溯算法]斐波那契数列与变形

本文分享了动态规划的基本三准则——状态抽象、转移方程与状态初始化,以斐波那契数列和青蛙跳台阶为例,探讨了如何运用这三个步骤解决问题。同时,通过代码优化展示了空间复杂度的思考,并介绍了动态规划的常见应用和技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好这是我的一个新的专题,动态规划,这里有我大量学习DP(动归)的学习笔记,和我的见解,但是博主在这一块一个是一个小白,还在摸索如果有我那里有错误,或者有更好的思路请你在评论区留言


动态规划三加一准则

三:

状态定义

转移方程

定义初始状态


一:

数组(一维,二维)

其中比较难得的就是状态的定义和转移方程,一般把这俩个想明白定义出来,那么这个道题基本上可以算是写出来了。一般来说状态定义都是从问题中抽象出来的……

你或许好奇为啥要数组呢?

因为DP其实也是一个分治的算法(大问题化成小问题),DP一般都要把之前的子问题求出来的解保存起来,因为后面需要子问题的解去推导更大的子问题。如果我分解出来不用我分小问题的意义何在,一般来说是用数组来保存


斐波那契数列


题目描述:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保失败,源站可能有防盗链机制,建议将图片保存下来直接上传存下来(img-74ARCSxj-1641556661131)(/Users/wuxiaobo/Library/Application Support/typora-user-images/image-20211225122853440.png)(/Users/wuxiaobo/Library/Application Support/typora-user-images/image-20211225122853440.png)]


分析:

很显然题目给了我们很多的信息,那么我们来看看如何把他抽象出来


状态定义:

题目告诉说 x 是由 x的前一项(x-1) + x的前前一项(x-2),那么我们就可以求第 i项 ,在用i的解去推 x ,所以我们需要一个数组去保存i项的解


状态初始化:

在题目中给给的分段函数可以看出x=1,x=2 时为一,那么这就是他的初始状态


递推方程:

题目其已经给我们写出来就是 fib(x-1)+fib(x-2),求当前一项需要知道前面俩项的结果

代码:

    int Fibonacci(int n) 
    {
        if(n==0)//处理特殊情况
        {
            return 0;
        }
            
        //状态定义
        int * fib=new int[n+1];
        //状态初始化
        fib[1]=1;
        fib[2]=1;
        //转移方程
        for(int i=3;i<=n;i++)
        {
            fib[i]=fib[i-1]+fib[i-2];
        }
        
        //返回结果
       return  fib[n];
    }
};

i项其实就是一个笼统的概念,其实需要好多个i项,就和之前一本书名字叫《5分钟学好英语》,内容也没错,知识5分钟学完之后你要花几千几万个5分钟进行复习……

上面的代码你看出哪里还有可以优化的地方嘛?

提示空间复杂度

……

……

……

……

……

我需要求第i项我是不是只需要知道 i-1 和 i-2 ,但是我不需要 知道 i-3……i-n 的值,那么我们可以用俩个变量进行动态更新

int Fibonacci(int n) 
    {
        if(n==0)//处理特殊情况
        {
            return 0;
        }
            
        //状态定义 //状态初始化
         int third=1;
         int second=1;
         int frist=1;
       
        //转移方程
        for(int i=3;i<=n;i++)
        {
          
            third=second+frist;
            //更新状态
            frist=second;
            second=third;
        }
        
        //返回结果
       return third;
    }
};


青蛙跳台阶


题目描述:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ncmzsQv2-1641556661133)(/Users/wuxiaobo/Library/Application Support/typora-user-images/image-20211225125420548.png)]


分析:

当青蛙跳到第n级台阶时,那么他要从哪里一级台阶跳上来呢?根据题目来看这应该不是火箭🐸,这只青蛙只可以跳 一层 或者 俩层 ,那只有俩种可能 就是在 n-1级的台阶 或 n-2级的台阶…………有没有很熟悉的感觉,这不就是披着羊皮的斐波那契嘛

那么我们就套用斐波那契的思路,从题中可以看出青蛙只有俩种跳法: 1级台阶 2级台阶

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hWvJAS6O-1641556661133)(/Users/wuxiaobo/Library/Application Support/typora-user-images/image-20211225130801332.png)]

初始状态:

由图所示,初始状态就是 青蛙可以跳的台阶级数, x=1 是为1 x=2 时为2,但是题目中有一个反人类的操作就是当是第0层的时候青蛙也跳了一次,所以初始状态为 x=0 为1 x=1 为1


代码

int numWays(int n)
    {
            
        //状态定义 //状态初始化
        int  third=1;
        int second=1;
        int frist=1;
       
        //转移方程
        for(int i=2;i<=n;i++)
        {
            third=second+frist;
            frist=second;
            second=third;
        }
        
        //返回结果
       return third;
    }

唠唠家常

记住动态规三加一口诀,状态抽象,转移方程,状态初始化,与一个数组保存中间的解
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值