问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

递推算法经典例题详解

创作时间:
作者:
@小白创作中心

递推算法经典例题详解

引用
CSDN
1.
https://blog.csdn.net/2302_79295270/article/details/134600379

递推在C语言学习中是一个十分关键的思想,我们最初的递推可以源于数学的全排列,递推规律(数列)甚至脑筋急转弯(高考题中也有递推的数列题(emm,概率和统计那块(全国卷为例))),而这里整理了一些递推 经典题,目的是帮助读者理清递推的思路。

经典例题1:爬楼梯

题目描述

欧老师爬楼梯,他可以每次走 1 级或者 3 级,输入楼梯的级数,求不同的走法数。

输入格式

输入包含若干行,每行包含一个正整数 N,代表楼梯级数,1<=N<=30。

输出格式

不同的走法数,每一行输入对应一行输出。

样例

输入

1
3
5

输出

1
2
4

解题思路

这道题的递推式为 F(n) = F(n-1) + F(n-3)。因为到达第 n 级楼梯有两种方式:从第 n-1 级跨一步,或从第 n-3 级跨三步。

代码实现

//递推爬楼梯
#include<stdio.h>
int oy(int n)
{
    if(n==1 || n==2) // 特殊情况处理
        return 1;
    if(n==3)
        return 2;
    else 
        return oy(n-1) + oy(n-3);
}
int main()
{
    int a[1000], i=0;
    while(scanf("%d", &a[i]) != EOF)
    {
        a[i] = oy(a[i]);
        i++;
    }
    for(int j=0; j<i; j++)
    {
        printf("%d\n", a[j]);
    }
    return 0;
}

例题2:全排列

题目描述

输入一个数 N,求 1 到 N 的全排列。

输入格式

输入一个 N,N<12。

输出格式

输出 N 的全排列,每个数字占 4 个位置。

样例

输入

3

输出

   1   2   3
   1   3   2
   2   1   3
   2   3   1
   3   1   2
   3   2   1

解题思路

使用深度优先搜索(DFS)算法来生成全排列。DFS是一种常见的图搜索算法,从根节点开始,沿着一条路径一直搜索下去,直到到达最深的节点或无法继续搜索为止,然后回溯到上一个节点,继续搜索其他路径,直到所有节点都被访问过为止。

代码实现

#include<stdio.h>
int p[10000]={0}, l[1000]={0};
int k;
void oy(int n)
{
    if(n==k+1)
    {
        for(int i=1; i<=k; i++)
            printf("%d ", p[i]);
        printf("\n");
        return;
    }
    for(int i=1; i<=k; i++)
    {
        if(l[i]==0)
        {
            p[n] = i;
            l[i] = 1;
            oy(n+1);
            l[i] = 0;
        }   
    }
    return;
}
int main()
{
    scanf("%d", &k);
    oy(1);
    return 0; 
}

例题三:成群的奶牛

题目描述

现有 n 只奶牛在一片宽广的草地上吃草,草地有一些小路,可以去到其他草场。这些小路都是单向的。每个草场有 2 条小路可以去到其他草场,但是只有 1 条小路可以到达这个草场。奶牛从其中一个草场开始,每遇到一个草场,奶牛们会精确地分成两群,这两群奶牛数量之差的绝对值为 k,分别从两条路去到下一个草场(如果数量不满足要求就不会再分裂)。当来到一个草场而该奶牛群已不可再分割时,奶牛们就会停下来在这里吃草。现给出 n 和 k,求奶牛最终会分成多少群。

输入格式

一行,分别是 n 和 k,用空格隔开。

输出格式

一个正整数,表示最终奶牛会分成多少群。

样例

输入

50 4

输出

2

数据规模与约定

0<n≤10000
0<k<n

解题思路

每次分裂后的两个数为 (n-k)/2 和 (n+k)/2,不满足的条件要么现在这个数比 k 小,要么分解后是分数(这个怎么去表示?(分数用相加不等于原数表示))。

代码实现

//成群的奶牛
#include<stdio.h>
int a, b;
int o=1;
void oy(int n)
{
    int p=(n-b)/2;
    int l=(n+b)/2;
    if(p+l != n)
        return;
    o++;
    if(p > b)
        oy(p);
    if(l > b)
        oy(l);
}
int main()
{
    scanf("%d %d", &a, &b);
    oy(a);
    printf("%d", o);
    return 0;
}

例四:初级快速幂训练

题目描述

请你计算 a 的 n 次方是多少,由于答案可能会很大,所以你只需要输出答案和 b 取余数的结果。

输入格式

多组输入,EOF 结束。每组一行,输入三个非负整数分别表示 a, n, b,(a, b, n 均在 int 范围内)。

输出格式

对于每一组输入,在新的一行输出结果。

样例

输入

2 10 10
3 3 5

输出

4
2

解题思路

使用二分法递归快速幂算法,本质上是分治算法。

代码实现

//初级快速幂(分治或者递归思想)
#include<bits/stdc++.h>
using namespace std;
long long oy(long long a, long long n, long long b)
{
    if (n <= 1)
    {
        if (n == 0)
            return 1 % b;
        else
            return a % b;
    }
    long long half = n / 2;
    long long tem = oy(a, half, b);
    if (n % 2 == 0)
    {
        return (tem * tem) % b;
    }
    else
    {
        return (tem * oy(a, half + 1, b)) % b;
    }
}
int main()
{
    long long int a, n, b, i=0, o[100000];
    while (scanf("%lld %lld %lld", &a, &n, &b) != EOF)
    {
        o[i] = oy(a, n, b);
        i++;
    }
    for(int j=0; j<i; j++)
    {
        printf("%d\n", o[j]);
    }
    return 0;
}

例五:分型三角形

题目描述

有一些少数民族的图腾是分形三角形,你能画出来吗?

输入格式

一个整数 n,表示图腾的大小。

输出格式

若干行,表示图腾的样子。

样例

输入

3

输出

       /\
      /__\
     /\  /\
    /__\/__\
   /\      /\
  /__\    /__\
 /\  /\  /\  /\
/__\/__\/__\/__\

数据规模与约定

1≤n≤10

解题思路

分型三角形的绘制可以通过递归实现,每次将一个三角形分为四个更小的三角形。

代码实现

#include <stdio.h>
#include <string.h>

void draw_triangle(int n, int row, int col, char triangle[20][40])
{
    if (n == 0)
        return;

    // Draw the top triangle
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 2 * n - 1; j++)
        {
            if (j >= col - i && j <= col + i)
                triangle[row + i][col - i + j] = (j % 2 == 0) ? '/' : '\\';
        }
    }

    // Draw the bottom left triangle
    draw_triangle(n - 1, row + n, col - n, triangle);

    // Draw the bottom right triangle
    draw_triangle(n - 1, row + n, col + n, triangle);
}

int main()
{
    int n;
    scanf("%d", &n);

    char triangle[20][40];
    memset(triangle, ' ', sizeof(triangle));

    draw_triangle(n, 0, 2 * n - 1, triangle);

    for (int i = 0; i < 2 * n - 1; i++)
    {
        for (int j = 0; j < 4 * n - 3; j++)
        {
            printf("%c", triangle[i][j]);
        }
        printf("\n");
    }

    return 0;
}

例六:超级楼梯

题目描述

有一楼梯共 M 级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第 M 级,共有多少种走法?

输入格式

输入数据首先包含一个整数 N,表示测试实例的个数,然后是 N 行数据,每行包含一个整数 M(1<=M<=40),表示楼梯的级数。

输出格式

对于每个测试实例,请输出不同走法的数量。

样例

输入

2
2
3

输出

1
2

解题思路

这道题的递推式为 F(n) = F(n-1) + F(n-2)。因为到达第 n 级楼梯有两种方式:从第 n-1 级跨一步,或从第 n-2 级跨两步。

代码实现

//超级楼梯
#include<stdio.h>
int oy(int n)
{
    if(n==1)
        return 1;
    if(n==2)
        return 1;
    else
        return oy(n-1) + oy(n-2);
}
int main()
{
    int i, a, b[10000];
    scanf("%d", &a);
    for(i=0; i<a; i++)
    {
        scanf("%d", &b[i]);
        b[i] = oy(b[i]);
    }
    for(int j=0; j<i; j++)
    {
        printf("%d\n", b[j]);
    }
    return 0;
}
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号