算法基础16 —— 递推(铺骨牌问题 + 信奥一本通 1313 位数问题 + NOIP 2002 过河卒)

2021-11-15————骨牌问题————c++基础之递推 有2 × n的一个长方形方格,要用若干1 × 2的骨牌铺满方格。例如,n = 3时,为2 × 3 方格,此时用3个1 × 2的骨牌铺满方格共有3种铺法。 编程输入一个n,输出铺法的总方案数。 输入 一个整数,n。 输出 一个数,输出总方案数 样例输入 3 样例输出 3 代码 #include<cstdio> #include<iostream> #include<cstring> #include<cmath> using namespace std; int 阅读详情
基本概念

所谓递推,是指从已知的初始条件出发,依据某种递推关系,逐次推出所要求的各中间结果及最后结果。初始条件如何得到呢?其实,初始条件要么是问题本身已经给定,要么是通过对问题的分析与化简后确定的

递推的方式
  • 顺推
  • 逆推
递推的特点

可用递推算法求解的题目一般有以下两个特点:

  • 问题可以划分成多个状态;
  • 除初始状态外,其它各个状态都可以用固定的递推关系式来表示。
递推入门 — Fibonacci数列

1、1、2、3、5、8、13… …

递归写法:

#include <iostream>

using namespace std;

int fb(int n)
{
	//printf("当前调用的是第%d层\n",n);
    if (n == 1 || n == 2) return 1;
    return fb(n - 1) + fb(n - 2);
}

int main()
{
    int n;
    cin >> n;
    cout << fb(n);
    return 0;
}

由下图中的递归搜索树,会发现存在很多重叠子问题
在这里插入图片描述
去掉注释之后,执行的结果如下:

当前调用的是第6层
当前调用的是第5层
当前调用的是第4层
当前调用的是第3层
当前调用的是第2层
当前调用的是第1层
当前调用的是第2层
当前调用的是第3层
当前调用的是第2层
当前调用的是第1层
当前调用的是第4层
当前调用的是第3层
当前调用的是第2层
当前调用的是第1层
当前调用的是第2层
8

记忆化搜索写法
将结果存储在b数组中

#include <iostream>

using namespace std;

int b[10010];//b[i]表示第i个元素的值
int fb(int n)
{
	if (b[n]) return b[n];//核心:查询b[n]是否非0,非0则直接返回本身
	//printf("当前调用的是第%d层\n",n);
    if (n == 1 || n == 2) return 1;
    b[n] =  fb(n - 2) + fb(n - 1);
    return b[n];
}

int main()
{
    int n;
    cin >> n;
    cout << fb(n);
    return 0;
}

去掉注释之后,执行的结果如下:调用层数明显减少

当前调用的是第6层
当前调用的是第4层
当前调用的是第2层
当前调用的是第3层
当前调用的是第1层
当前调用的是第2层
当前调用的是第5层
8

递推写法

#include <iostream>
using namespace std;
long long dp[55];
int main()
{
    int n;
	cin >> n;
    dp[1] = 1;
    dp[2] = 1;
    for (int i = 3;i <= 50;i++) dp[i] = dp[i - 1] + dp[i - 2];
	cout << dp[n];
	return 0;
}

递推 — 铺骨牌问题

有2 × n的一个长方形方格,用一个1 × 2的骨牌铺满方格。编写一个程序,试对给出的任意一个n(n>0), 输出铺法总数

算法分析

  • 当n = 1时,只能是一种铺法,铺法总数有示为1
  • 当n = 2时,骨牌可以两个并列竖排,也可以并列横排,再无其他方法,铺法总数表示为2
  • 当n=3时,骨牌可以全部竖排,也可以认为在方格中已经有一个竖排骨牌,则需要在方格中排列两个横排骨牌(无重复方法),若已经在方格中排列两个横排骨牌,则必须在方格中排列一个竖排骨牌,再无其他排列方法,因此铺法总数表示为3
  • 由此可以看出,当n = 3时的排列骨牌的方法数是n = 1和n = 2排列方法数的和

推出一般规律:
对一般的n,设Xn表示n个骨牌一共有多少种的排列方法。若第一个骨牌是竖排列放置,剩下有n - 1个骨牌需要排列,这时排列方法数为Xn-1;若第一个骨牌是横排列,整个方格至少有2个骨牌是横排列,因此剩下n - 2个骨牌需要排列,这时骨牌排列方法数为Xn-2。从第一骨牌排列方法考虑,只有这两种可能,所以有:Xn = Xn-1 + Xn-2 (n > 2)
这就是问题求解的递推公式,当n = 1和n = 1时,答案已知,故任意给定的n都可以从递推中获得解答


经典例题:位数问题(信奥一本通1313)

原题链接
题目描述

在所有的N位数中,有多少个数中有偶数个数字3?由于结果可能很大,你只需要输出这个答案对12345取余的值。

输入格式

读入一个数N(1<=N<=1000)

输出格式

输出有多少个数中有偶数个数字3

输入样例

2

输出样例

73

样例说明

在所有的2位数字,包含0个3的数有72个,包含2个3的数有1个,共73个

分析:
① 当N取1时,所有的一位数为0、1、2、3、4、5、6、7、8、9,其中,含偶数个3的数字为0、1、2、4、5、6、7、8、9,共9个
② 当N取2时,分两种情况。

  • 若第二个数字是3,那么第一个数字必也是3(两个3);
  • 若第二个数字不是3(九种情况),第一个数字也不是3且不能为0(八种情况),共8 x 9 = 72种可能。

综上,当N取2时,一共有73个数字包含偶数个3
不妨设f[n][0]表示包含偶数个3的n位数的个数。
不妨设f[n][1]表示包含奇数个3的n位数的个数。

那么,如何得到n位数中包含偶数个3的方案数呢?
如下图,假设一个n位数最后一位数字是3,那么只有满足其前n - 1位包含奇数个3,才可以使n位包含偶数个3,即f[n - 1][1]
在这里插入图片描述
如下图,假设一个n位数最后一位数字不是3,可能取0、1、2、4、5、6、7、8、9(最后一位有9种情况),那么只有满足其前n - 1位包含偶数个3,才可以使n位包含偶数个3,即f[n - 1][0] * 9
在这里插入图片描述
由以上分析得:

f[n][0] = f[n - 1][1] + f[n - 1][0] * 9 

同理:

f[n][1] = f[n - 1][0] + f[n - 1][1] * 9

AC代码

#include <iostream>

using namespace std;

const int N = 1010;
//f[i][0]:i位数中包含偶数个3的方案数
//f[i][1]:i位数中包含奇数个3的方案数
int f[N][2];

int main()
{
    int n;
    cin >> n;
    
    //初始化
    //f[1][0]:一位数中包含偶数个3的方案数(0 1 2 4 5 6 7 8 9)
    //f[1][1]:一位数中包含奇数个3的方案数(3)
    f[1][0] = 9;
    f[1][1] = 1;
    
    //递推
    for (int i = 2;i <= n;i++)
    {
        int num = 9;//非首位元素可以为0,有9种可能
        if (i == n) num = 8;//首位元素不能为0,有8种可能
        f[i][0] = (f[i - 1][1] + f[i - 1][0] * num) % 12345;
        f[i][1] = (f[i - 1][0] + f[i - 1][1] * num) % 12345;
    }
    
    //f[n][0]:n位数中包含偶数个3的方案数
    cout << f[n][0] << endl;
    return 0;
}

过河卒问题

原题链接
问题描述

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n,m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。

在这里插入图片描述
DFS写法:

递推写法:
分析:要到达棋盘上的一个点,只能从左边过来或是从上面过来,根据加法原理,到达某一点的路径数目,就等于到达其相邻的上点和左点的路径数目之和

状态设计:用F[i][j]表示从起点到达点(i,j)的路径数目,g[i][j]表示点(i, j)有无障碍,g[i][j] = 0表示无障碍,g[i][j] = 1表示有障碍

递推关系式如下:

F[i][j] = F[i-1][j] + F[i][j-1] //i>0且j>0且g[i][j]= 0

递推边界有4个:

F[i][j] = 0 //g[i][j] = 1
F[i][0] = F[i-1][0] //i > 0且g[i][j] = 0
F[0][j] = F[0][j-1] //j > 0且g[i][j] = 0
F[0][0] = 1

考虑到最大情况下:n = 20,m = 20,路径条数可能会超过2^31-1,所以要用long long

动态规划经典例题汇总 (附最全题目链接) 本文总结了王道机试指南中动态规划(Dynamic Progamming)部分的所有例题。 一.基本思想 与分治法类似,其基本思想也是将待求解问题分解成若干子问题,先求解子问题,然后从这些子问题的解中得到原问题的解。 与分治法不同的是,分治法会使得有些子问题被重复计算多次。而动态规划的做法是将已解决子问题的答案保存下来,在需要子问题答案的时候便可直接获得,而不需要重复计算,节约效率。 二.经典题目 ... 阅读详情

相关推荐

comsol 多物理场仿真流程-以开关柜为例

1、主要方法 在SolidWorks中对于开关柜的内部与外部结构进行建模,生成能够导入软件计算的3D模型。将SolidWorks中的模型导入comsol软件中,设置参数进行多物理场耦合仿真。 1、具体步骤 删除高压开关柜中对其内部电磁环境无较大影响的结构,如低压测量柜、断路器内部结构等。 导入模型:将厂家提供的3D模型转化为solidworks结构模型。 修复模型:修复已转化模型中转化错误的部分、修复已转化模型中非实体部分、修复已转化模型中重叠实体部分 化简模型:去除过于...

健忘16的博客 7020

青少年C++编程NOIP/CSP竞赛通关语法-一维数组

本课程为零基础C++语法专题课,是青少儿参加信息学奥赛NOIP/CSP需要学习的语法专题课;2、本课程每节课均配有练习题以及真题,以锻炼孩子的解题能力;3、本课程是基于小学生的认知发展水平开发的,运用孩子生活中常见的例子来阐述编程知识,让孩子听得懂学得会;4、学完本课程后,孩子可以自主编程,解决竞赛中,生活实际问题,5、拓展孩子计算思维,应对人工智能时代的挑战。6、本课程介绍的是一维数组。也是历来竞赛重要考点。

什么是无人机电源管理模块?电源管理模块有什么用处?

我来描述一下我的问题情景,电源管理模块的定义是,这里给出这个PX4官方对于电源管理模块的一些介绍,补充一下锂电池的放电原理大家就可以更好理解为什么需要电源管理模块

HRWVY0725的博客 2273

骨牌铺方格(递推)

原题链接 Problem Description 在2 × n的一个长方形方格中,用一个1 × 2的骨牌铺满方格,输入n ,输出铺放方案的总数.例如n=3时,为2 × 3方格,骨牌的铺放方案有三种,如下图: Input 输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2×n (0<n<=50)。 Output 对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。 Sample Input 1 3 2 Sample Output 1 3 2

smallrain6的博客 9406

Android实现TextToSpeech控件实现语音播报--朗读文字 (附完整源码)

Android实现TextToSpeech控件实现语音播报--朗读文字 (附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1116

Linux 内核中 ARP 协议的全链路解析:从触发机制到物理层发送

核心设计思想按需解析:减少不必要的 ARP 请求,降低网络负载。分层解耦:协议栈各层(邻居子系统、Netfilter、驱动)职责分离,提高扩展性。ARP的核心作用是将IP映射为MAC地址,确保数据链路层能正确封装帧。其触发时机围绕“未知MAC地址需求”展开,覆盖通信初始化、缓存更新、网络变更及维护等多种场景。

数字人生 367

[信息学奥赛一本通-T1314]过河卒-题解

思考: 1.判断A(0,0)到达B(n,m)可以有两种情况: A点的方向:(1)从B点上方来(2)从B点左边来 当n!=0&&m!=0时:F(i,j)=F(i-1,j)+F(i,j-1); 2.考虑边界问题: i=0时,F(i,j)+=F(i,j-1),只能从左边来 j=0时,F(i,j)+=F(i-1,j),只能从上面来 3.用一个二维数组dir[8][2]表示马可以走的8个方向,第1列表示x的移动坐标,第2列表示y的移动坐标 4.对于马的坐标和马的控制点,我们需要用一个二维数组d[25]

m0_46549788的博客 855

SAP DRC 是什么?一文读懂 SAP Document and Reporting Compliance 的定位、架构与落地案例

把视线拉长,会发现SAP DRC的价值并不仅是用来交差的工具。它更像是企业在全球化经营中建设的一套公共底座:既能以最低的重复成本去应对各国不断演进的监管要求,也能为财务数字化与供应链协同提供可信数据回路。依托本地与云的分层职责、与的生态联动、以及按国家不断更新的任务目录,企业可以将合规变成一种标准化、工程化、可持续运营的能力。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1652

递推算法-五种典型的递推关系

目录 递推算法 有关Fibonacci数列 兔子产子问题 【例3】骨牌的铺法 五种典型的递推关系 Ⅰ.Fibonacci数列 Ⅱ.Hanoi塔问题 Ⅲ.平面分割问题 Ⅳ.Catalan数(卡塔兰数 ) Ⅴ.第二类Stirling数(斯特林数 小结: 例题 递推算法 递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法。这种算法特点是:一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系,在计...

默默无闻但不碌碌无为 4652

FISCO BCOS(八)——— 一键部署 WeBase

环境 版本 Java Oracle JDK 8 至 14 MySQL MySQL-5.6及以上 Python Python3.6及以上 PyMySQL 1、获取部署安装包: wget https://osp-1257653870.cos.ap-guangzhou.myqcloud.com/WeBASE/releases/download/v1.5.4/webase-deploy.zip 2、解压安装包: unzip webase-deploy.zip 3、进入目录: c...

林中有神君 3607

如何用Python打造PubMed API客户端:科研文献检索自动化实践

PubMed提供了官方的Entrez E-utilities API接口,支持程序化检索文献,但直接调用API需处理请求重试、参数封装、数据解析等问题。批量获取文献ID及结构化详情(标题、作者、DOI等)内置重试机制,应对网络波动或API限流统一数据输出格式,便于后续分析(如文献计量、AI文本处理)灵活适配不同检索需求(如指定数据库、结果数量)本文实现的PubMed API客户端,通过封装API请求、重试机制、数据解析,让科研文献检索从“手动点击”变为“代码自动化”。

ASKCOS博客 358

算法整理三——递推

目录 递推算法概述 一、求菲波那契数列 二、汉诺塔(Tower of Hanoi)问题 三、猴子吃桃 四、数字三角形(顺推法) 五、骨牌铺满方格 六、吃糖果 七、蜜蜂路线 八、昆虫繁殖【这题有点点难哦】 九、位数问题 十、分苹果 十一、踩方格 十二、爬楼梯(openjudge题目) 递推算法概述 递推/递归既可以理解成是一种算法思想,也可以理解成是一种算法的实现方式 分治算法策略主要通过递归实现,大规模问题分解成小规模问题;动态规划算法主要通过递推实现 递归和递推的

weixin_45901806的博客 9138

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

骨牌铺法(满分详解)

大家好啊,我是你们熟悉的柚子味哈牛,不过……最近改名了,沐隗顾梦好听吗,以后你们可以叫我沐隗,也可以叫顾梦。OKK,进入正题今天给大家讲的是一道很经典的递推问题。

wzy20090611520的博客 862

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

递归递推问题(DP?)

有1×n的一个长方形,用一个1×1、1×2和1×3的骨牌铺满方格。例如当n=3时为1×3的方格。此时用1×1、1×2和1×3的骨牌铺满方格,共有四种铺法。输入输入整数n输出输出铺法总数样例输入3样例输出4提示n <= 40。

2301_80449661的博客 1473

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

递推与递归

递推与递归

m0_55341679的博客 376

递推算法---骨牌填充

题目: 在2×n的一个长方形方格中,用一个2× 1的骨牌铺满方格,例如n=3时,为2× 3方格,骨牌的铺放方案有三种(如图)。求输入n,输出铺放方案的总数 分析: 可以把2× 1的骨牌看成一个整体,可以竖着放,也可以横着放。 第N张牌的排列可以由N-1张牌的排列再在末尾加上一张竖的牌。这样依然合法。也可以在N-2张合法排列的牌后面加上两张横着放的牌(如果竖着放就和上面一种重复了)。

bojiujiu的专栏 1250

骨牌铺方格(递归,递推)

/用斐波那契数列型公式就可以解决,发现早就有大佬解决了。~~~//仅当笔者个人备忘录使用。

Sky_miracle的博客 601

OJ密码岛 1851. 过河卒(Noip2002)

题目描述 棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m)(n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。 输入格式 给出n、m和C点的坐标。 输出格式 从A点能够到达B点的路径.

daaaadd的博客 769

骨牌铺方格的3种做法

应对题目:用1*2的骨牌铺满n*m的矩形总共有多种方法 方法1:状压DP: 复杂度:n*m*(2^m) 解题过程: 1、为了提高效率,我们规定m=m就交换         2、以单个格子作为每个阶段,递推方向为从左上到右下,每个阶段储存前m个方块的状态,1表示已覆盖,0表示未覆盖         3、阶段决策是:"以当前格子为右下角,要不要放骨牌以及放哪种骨牌",答案有3种:不

加载中... 2931

【递推算法问题详解:超级楼梯与骨牌铺方格】

本文详细探讨了具有递推性质的"超级楼梯"和"骨牌铺方格"问题,通过详细分析,得出了递推表达式及相应的编程实现。针对不同的问题场景,还进行了问题拓展和深入分析。

B_T_D的博客 2586

骨牌铺法(c++)

题目描述 骨牌铺法(domino) 【问题】有1*n的一个长方形,用一个1*1、1*2、1*3的骨牌铺满方格。 例如n=3时为1*3的方格。 此时用1*1、1*2、1*3的骨牌铺满方格,共有四种铺法。 即3个1*1、1个1*1+1个1*2、1个1*2+1个1*1、1个1*3。 输入 【输入】n 输出 【输出】铺法总数 样例输入 6 样例输出 24 好我们来看 它这个题跟其他类型的骨牌铺法不同,它的骨牌分3种,并不是1种骨牌 所以直接推 1×

2201_75777958的博客 2606

3.骨牌问题

线性DP

weixin_60869516的博客 760

铺满骨牌的方案

在学习动态规划时的入门练习题,没有找到具体题目,不过觉得推导过程不错,记录一下 题目: 在一个3 X N的长方形方格中,铺满1X2的骨牌(骨牌个数不限制),给定N求方案数。 先降低一下难度,考虑 2 X N 的长方形方格 比如:N=2 时方案数为 2 如果是 N 的方案,怎么求? 第 n 列,我们可以竖着放 1 个,也可以把 n - 1 列拿来,横着放 2 个 骨牌长度=2,不会影响 n - 2 列,所以 n 列的方案等同于: n - 1 列 + 竖放1个,或者 n-2.

mrbone9的博客 892

信息学奥赛一本通 1313:【例3.5】位数问题

【题目链接】 ybt 1313:【例3.5】位数问题 【题目考点】 1. 递推 【解题思路】 设M=123456M=123456M=123456 a[i]表示i位数的数字中,有偶数个3的数字的数量对M取模。 b[i]表示i位数的数字中,有奇数个3的数字的数量对M取模。 1位数只有数字333包含1个3,也就是奇数个3。其余9个数字都只包含0个3,也就是偶数个3。 那么a[1]=9 表示在1位数中有9个数字有偶数个3, b[1] = 1 表示在1位数中有1个数字有奇数个3。 2位数,就是在1位数前面添加一位

君义NOIP的博客 6037

骨牌铺方格【分治算法】

骨牌铺方格【分治算法】

m0_46308522的博客 3049
上一篇: 算法基础15 —— 分治算法(归并排序 + 快速排序)
下一篇: Dynamic Programming从入门到放弃 —— 第一章:数字三角形模型
Zsprinkle
博客等级 码龄8年 235粉丝 147原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值