递推(一):递推法的基本思想
所谓递推,是指从已知的初始条件出发,依据某种递推关系,逐次推出所要求的各中间结果及最后结果。其中初始条件或是问题本身已经给定,或是通过对问题的分析与化简后确定。
利用递推算法求问题规模为n的解的基本思想是:当n=1时,解或为已知,或能非常方便地求得;通过采用递推法构造算法的递推性质,能从已求得的规模为1、2、…、i−1的一系列解,构造出问题规模为i的解。这样,程序可从i=0或i=1出发,重复地由已知至i−1规模的解,通过递推,获得规模为i的解,直至获得规模为n的解。
可用递推算法求解的问题一般有以下两个特点: (1) 问题可以划分成多个状态; (2) 除初始状态外,其它各个状态都可以用固定的递推关系式来表示。当然,在实际问题中,大多数时候不会直接给出递推关系式,而是需要通过分析各种状态,找出递推关系式。
利用递推算法解决问题,需要做好以下四个方面的工作:
(1)确定递推变量
应用递推算法解决问题,要根据问题的具体实际设置递推变量。递推变量可以是简单变量,也可以是一维或多维数组。从直观角度出发,通常采用一维数组。
(2)建立递推关系
递推关系是指如何从变量的前一些值推出其下一个值,或从变量的后一些值推出其上一个值的公式(或关系)。递推关系是递推的依据,是解决递推问题的关键。有些问题,其递推关系是明确的,大多数实际问题并没有现成的明确的递推关系,需根据问题的具体实际,通过分析和推理,才能确定问题的递推关系。
(3)确定初始(边界)条件
对所确定的递推变量,要根据问题最简单情形的数据确定递推变量的初始(边界)值,这是递推的基础。
(4)对递推过程进行控制
递推过程不能无休止地重复执行下去。递推过程在什么时候结束,满足什么条件结束,这是编写递推算法必须考虑的问题。
递推过程的控制通常可分为两种情形:一种是所需的递推次数是确定的值,可以计算出来;另一种是所需的递推次数无法确定。对于前一种情况,可以构建一个固定次数的循环来实现对递推过程的控制;对于后一种情况,需要进一步分析出用来结束递推过程的条件。
递推通常由循环来实现,一般在循环外确定初始(边界)条件,在循环中实施递推。
递推法从递推方向可分为顺推与倒推。
所谓顺推法是从已知条件出发,通过递推关系逐步推算出要解决的问题的结果的方法。如求斐波拉契数列的第20项的值,设斐波拉契数列的第n项的为f(n),已知f(1)=1,f(2)=1;通过递推关系式f(n)=f(n-2)+f(n-1) (n>=3,n∈N),可以顺推出f(3)=f(1)+f(2)=2、f(4)=f(2)+f(3)=3、…直至要求的解f(20)=f(18)+f(19)=6765。
所谓倒推法,就是在不知初始值的情况下,经某种递推关系而获知了问题的解或目标,从这个解或目标出发,采用倒推手段,一步步地倒推到这个问题的初始情况。
一句话概括:顺推是从条件推出结果,倒推从结果推出条件。
顺推法是从前往后推,从已求得的规模为1、2、…、i−1的一系列解,推出问题规模为i的解,直至得到规模为n的解。顺推算法可描述为:
for (k=1; k<=i−1; k++)
f[k]= <初始值>; // 按初始条件,确定初始值
for (k=i; k<=n; k++)
f[k]= <递推关系式>; // 根据递推关系实施递推
cout<<f[n]; // 输出n规模的解f(n)
倒推法是从后往前推,从已求得的规模为n、n−1、…、i+1的一系列解,推出问题规模为i的解,直至得到规模为1的解(即初始情况)。倒推算法可描述为:
for (k=n; k>=i+1; k--)
f[k]= <初始值>; // 按初始条件,确定初始值
for (k=i; k>=1; k--)
f[k]= <递推关系式>; // 根据递推关系实施递推
cout<<f[1]; // 输出问题的初始情况f(1)
递推问题一般定义一维数组来保存各项推算结果,较复杂的递推问题还需定义二维数组。例如,当规模为i的解为规模为1、2、…、i−1的解通过计算处理决定时,可利用二重循环处理这一较为复杂的递推。
【例1】RPG涂色问题
有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三种颜色涂每个格子,每个格子涂一种色,要求任何相邻的方格不能同色,且首尾两格也不同色。
编写一个程序,输入方格数n(0<n<=30),输出满足要求的全部涂法的种数。
(1) 编程思路
设满足要求的n个方格的涂色方法数为F(n)。
因为RPG有三种颜色,可以先枚举出当方格数为1、2、3时的涂法种数。
显然, F(1)=3 (即R、P、G三种)
F(2)=6 (即RP、RG、PR、PG、GR、GP六种)
F(3)=6 (即RPG、RGP、PRG、PGR、GRP、GPR六种)
当方格的个数大于3时,n个方格的涂色方案可以由n-1方格的涂色方案追加最后一个方格的涂色方案得出,分两种情况:
1)对于已按要求涂好颜色的n-1个方格,在F(n-1)种合法的涂色方案后追加一个方格(第n个方格),由于合法方案的首尾颜色不同(即第n-1个方格的颜色不与第1个方格的相同),这样,第n个方格的颜色也是确定的,它必定是原n-1个方格的首尾两种颜色之外的一种,因此,在这种情况下的涂色方法数为F(n-1)。
2)对于已按要求涂好颜色的n-2个方格,可以在第n-1个方格中涂与第1个方格相同的颜色,此时由于首尾颜色相同,这是不合法的涂色方案,但可以在第n个方格中涂上一个合法的颜色,使其成为方格长度为n的合法涂色方案(注意:当n等于3时,由于第1(3-2)个方格与第2(3-1)个方格颜色相同,第3个方格不论怎样涂都不会合法,因此递推的前提是n大于3),在第n个方格中可以涂上两种颜色(即首格外的两种颜色,因为与它相连的第n-1个方格和第1个方格的颜色是一样的),因此,在这种情况下的涂色方法数为2*F(n-2)。
由此,可得递推公式:F(n)= F(n-1) + 2*F(n-2) (n>=4)
程序中定义3个变量f1、f2和f3分别表示F (n-2)、F(n-1)和F(n),初始时f1=6、f2=6。
当n<4时,根据初始情况直接输出结果。
当n>=4时,用循环递推计算F(n)。程序段描述为:
for(i=4;i<=n;i++)
{
f3=f1+f2; // 计算当前F(i)
f1=f2; f2=f3; // 为下一次递推做准备
}
(2)源程序及运行结果
#include <iostream>
using namespace std;
int main()
{
int i,n,f1,f2,f3,num;
cout<<"请输入方格的数目 n (0<n<=30):";
cin>>n;
if (n==1) num=3;
else if (n==2 || n==3) num=6;
else
{
f1=6; f2=6;
for(i=4;i<=n;i++)
{
f3=2*f1+f2; // 递推求F(i)
f1=f2; f2=f3; // 为下次递推做准备
}
num=f3;
}
cout<<n<<"个方格的正确涂色方案一共有"<<num<<"种。"<<endl;
return 0;
}
为更清晰地描述递推过程并保存中间结果,可以定义一个一维数组f[31],数组元素f[i]保存总数为i个方格的涂色方法数。初始值: f[1]=3、f[2]=6、f[3]=6。源程序清单如下。
#include <iostream>
using namespace std;
int main()
{
int i,n,f[31];
f[0]=0;
f[1]=3;
f[2]=6;
f[3]=6;
for(i=4;i<31;i++)
f[i]=f[i-1]+2*f[i-2];
cout<<"请输入方格的数目 n (n<=30):";
cin>>n;
cout<<n<<"个方格的正确涂色方案一共有"<<f[n]<<"种。"<<endl;
return 0;
}
转载于:https://www.cnblogs.com/cs-whut/p/11022438.html
递推(一):递推法的基本思想相关推荐
- 递 归 ,递 推 ,贪 心,学 习 总 结
目 录 壹 :递 归 一 . 递 归 初 步( 理 论 ) 二 . 递 归 深 入( 习 题 ) 贰 :递 推 一 . 递 推 初 步 ( 理 论 ...
- 算法设计与分析 2 二维递推间接递推递归分析
二维递推&间接递推&递归分析 二维递推 走地图 #include<stdio.h> #define MAX 200 int f[MAX][MAX]; int Go(int ...
- 【组合数学】递推方程 ( 递推方程示例 1 | 列出递推方程 )
文章目录 一.递推方程示例 1 二.递推方程示例小结 一.递推方程示例 1 编码系统使用 888 进制数字 , 对信息编码 , 888 进制数字只能取值 0,1,2,3,4,5,6,70,1,2,3, ...
- 【组合数学】递推方程 ( 递推方程内容概要 | 递推方程定义 | 递推方程示例说明 | 斐波那契数列 )
文章目录 一.递推方程 内容概要 二.递推方程 定义 三.递推方程 示例 四.斐波那契数列 ( Fibnacci ) 一.递推方程 内容概要 递推方程 内容概要 : 递推方程定义 递推方程实例 常系数 ...
- 【组合数学】递推方程 ( 递推方程解与特征根之间的关系定理 | 递推方程解的线性性质定理 | 递推方程解的形式 )
文章目录 一.递推方程解与特征根之间的关系定理 二.递推方程解的线性性质定理 三.递推方程解的形式 一.递推方程解与特征根之间的关系定理 特征根 与 递推方程的解 之间是存在关系的 , 如果知道了这个 ...
- 【百科】CLEO 逐推縮寫命名法
一. 適用場合 1. C# Windows Forms 等窗體開發技術的控件名稱縮寫: 2. 強行縮寫駝峰命名法(Camel-Case).帕斯卡命名法的英文的時候: 二. 命名規則 1. 首字母大寫: ...
- 引导魔女之力,征服星辰大海 主线篇: 重要事情说三遍: 推主线!推主线!!推主线!!! 简述: 1.本篇仅主线,涉及到的技巧全职业都可以参考; 2.考虑到萌新刚玩没有护卫者系统,故禁护
引导魔女之力,征服星辰大海 主线篇: 重要事情说三遍: 推主线!推主线!!推主线!!! 简述: 1.本篇仅主线,涉及到的技巧全职业都可以参考: 2.考虑到萌新刚玩没有护卫者系统,故禁护卫者以及不使用卡 ...
- android推送接口,推送API
推送API 简述 个推为开发者提供了如下3种消息推送方式: toSingle :简称"单推",指向单个用户推送消息 toList:简称"批量推",指向制定的一批 ...
- 企业创新流程的“正向推”与“反向推”思考
近期一直做企业创新流程的建设工作,遇到两种场景,一类是从0开始建设创新流程.一类是前期已经构建了创新流程,在运作中遇到业务问题需要优化. 基于两类场景,我分享对创新流程的"正向推" ...
最新文章
- JQUERY搞的相册导航DEMO教学,总有一款合心意
- 一步一步教你在 Android 里创建自己的账号系统(一)
- C++虚继承和虚基类详解(一)
- 华为hcia H31-311 练习题
- 新增房源服务实现之新增房源RESTful接口的开发
- LeetCode 391. 完美矩形(set检查顶点+面积检查)
- python list元素合并_Python-列表+-01-两个列表各元素合并
- mongodb(2) 1
- ios创建自定义控件必须具备的三个方法
- 【React Native 安卓开发】----(View实战之仿携程)【第三篇】
- 外卖cps项目的玩法淘宝客经验分享
- 教你如何使用github+jsDelivr搭建免费图床
- PriorityQueue 改变排序方式,倒叙
- ”latest”(已经确认了的), “earliest”(创世区块的) , “pending”(包含未确认的交易的余额)
- cad工具箱详细讲解_CAD工具箱的12种功能详解
- 九、redis的删除机制
- 『Nginx』Nginx单双机热备方案实现
- 2019 前端工程师修炼手册.pdf
- 公众号h5页面分享并监测分享事件
- 高通atheros ar93xx AP软件体系结构