【算法笔记】递推方法及其例题讲解

递归与递推的区别

递归:从未知到已知 逐步接近解决问题的过程
递推:从已知到未知


递推常见内容

1.求方案数:往往需要进行乘法远离或加法原理进行累加
2.求最优值:一般没见过…
3.基础动态规划:有点难啊…


基础递推求解思路

基础递推的思考方式: 当你求第i个方案的时候,0~i-1的方案都是已知
主要的思考方式:把第i个元素加进去,对整个方案的影响
(下面会在例题中具体验证)
当然,个人还有两种非正规的解题方法:
1.暴力运行法:通过暴力运行的题目进行找规律
2.找规律:用笔演算,计算出部分小数据内容,并进行对递推式的推测
(至于证明么 …有一个好方法:数学归纳法)
但毕竟这两种方法不一定正确,但在一定程度上使题目的解答更加容易
当然还有:动态规划求解法:根据题意设置出状态和状态转移方程,一般难度较大


取数问题

题目描述
我们来玩一个游戏:自然数1到N,按顺序列成一排,你可以从中取走任意个数,但是相邻的两个不可以同时被取走。
如果你能算出一共有多少种取法,那么你会被天神Lijiganjun奖励。
输入格式
一个数n(1< n < = 50)。
输出格式
仅包含一个数——你的答案。
样例数据
input
5
output
13
数据规模与约定
时间限制:1s1s
空间限制:256MB

1.方法1:找规律
以1,2,3,4,5…n的数列为例
①n=1 有取1和不取两种
②n=2 数列1和2中:取1,取2,不取,有三种
③n=3 数列中1,2,3中:取1,取2,取3,取13,不取,有5种
④n=4 数列中1,2,3,4中:取1,取2,取3,取4,取13,取24,取14,不取,有8种
⑤n=5 由题意得,有13种
可见,当n=1-5时,ans[1-5]=2,3,5,8,13
不难发现,除了第一项和第二项,后面的每一项都是前面的两项的和,即斐波那契数列
可以得出递推式:f(i)=f(i-1)+f(i-2)
2.方法2:理解递推式的含义
设现在求的是n个数,n-1的方案数都是已知的
1.当这个数不取的时候,方案数是f(i-1)
2.当这个数取的时候,因为由题意得,数字是不能重复的,所以第n-1个数是不能选的,必然是从前n-2项的方案内容上多加一个n,故方案数是f(i-2).
综上所述,可得递推式是:f(i)=f(i-1)+f(i-2)


骨牌铺法

题目描述

有 1×n 的一个长方形,用一个 1×1、1×2 和 1×3 的骨牌铺满方格。例如当 n=3 时为 1×3 的方格。 此时 用 1×1、1×2 和 1×3 的骨牌铺满方格,共有四种铺法。如下图:
①o o o
②o x-x
③x-x o
④x-x-x
输入格式
一个整数 n n<=40
输出格式
一个整数表示方法总数
样例数据
input
3
output
4
数据规模与约定
时间限制:1s1s
空间限制:256MB

方法1:找规律
n=0 什么都不放,1种
n=1 “o”,共1种
n=2 “o o” “x-x”,共2种
n=3 由题意得,共4种
n=4 “o o o o” “o o x-x” “o x-x-x” “x-x x-x” “x-x o o” “x-x-x o” “o x-x o” 共7种
根据数列1,1,2,4,7,可得f(i)=f(i-1)+f(i-2)+f(i-3)
方法2:暴力运行
骨牌数为1可以看成数字1,骨牌数为2可以看成数字为2,骨牌数为3可以看成数字为3
样例中
3=1+1+1 共3种方法
=2+1
=1+2
=3
同理,你可以看成是数字拆分问题,同1,2,3去拼,用DFS或完全背包运行将结果运行出来,
同样可以得到递推式:f(i)=f(i-1)+f(i-2)+f(i-3)
方法3:
我们要求的是n个位置的方案数,则已知n-1的方案数.
可以看成是由n-3,n-2,n-1的位置加上3,2,1的方块拼成的n
故递推式为:f(i)=f(i-1)+f(i-2)+f(i-3)


递推专练1:(简单数位DP)

题目描述
在所有的N位自然数(不包含0)中,有多少个数中有偶数(0也是偶数)个数字3?
输入格式
读入一个数N。1<=N<=1000。
样例数据
input
2
output
73
数据规模与约定
时间限制:1s1s
空间限制:256MB256MB
注:
0个3也是偶数个3,但是1位数里不包含0.
由于结果可能很大,你只需要输出这个答案mod 12345的值。

这就是传说中的最简单的数位DP,我们可以根据数位,数字3的个数进行求解
1.我们需要设置数组f,表示偶数个3的个数;其次,我们需要设置数组g,表示奇数个3的个数
2.我们可以得出:f[i]表示i位数字中有偶数位3的个数,g[i]表示i位数字中有奇位的个数
3.设置初始化:1-9(0不能作为个位数可忽略不计,但在数位≥2是可以使用);f[1]=8,即没有3(0个数字3);g[1]=3,即个位数字3.
4.动态规划过程:枚举过程十分简单,即枚举位数i,可得:f[i]=f[i-1]*9+g[i-1],表示原来有偶数个3的数字加上不是3的任何一个数字,而奇数为的数字则加上数字3;同理,g[i]=g[i-1]*9+f[i-1].
代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
int g[10000]={
   0,1};
int f[10000]={
   0,8};
int main()
{
   
   	cin>>n;
   	for (int i=2;i<=n;i++)
   	{
   
   	    f[i]=(f[i-1]*9+g[i-1])%12345;
		g[i]=(g[i-1]*9+f[i-1])%12345;	
    }
    cout<<f[n];
    return 
  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值