• II.-递归


    目录

    A.汉诺塔

    B.N皇后

    C.波兰表达式

    D.表达式求值

    E.爬楼梯

    F.放苹果


    一个函数调用其自身,就是递归

    • 1)    替代多重循环
    • 2)    解决本来就是用递归形式定义的问题
    • 3)    将问题分解为规模更小的子问题进行求解

    A.汉诺塔


    问题描述

    有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘; 大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。

    问:如何移?最少要移动多少次?

    汉诺塔示意图如下:

    三个盘的移动:

    输入

    输入为一个整数后面跟三个单字符字符串。
    整数为盘子的数目,后三个字符表示三个杆子的编号。

    3 a b c

    输出

    输出每一步移动盘子的记录。一次移动一行。
    每次移动的记录为例如3:a->b 的形式,即把编号为3的盘子从a杆移至b杆。
    我们约定圆盘从小到大编号为1, 2, ...n。即最上面那个最小的圆盘编号为1,最下面最大的圆盘编号为n。

    1. 1:a->c
    2. 2:a->b
    3. 1:c->b
    4. 3:a->c
    5. 1:b->a
    6. 2:b->c
    7. 1:a->c

    题目解答

      解法的基本思想是递归。假设有A、B、C三个塔,A塔有N块盘,目标是把这些盘全部移到C塔。那么先把A塔顶部的N-1块盘移动到B塔,再把A塔剩下的大盘移到C,最后把B塔的N-1块盘移到C。 每次移动多于一块盘时,则再次使用上述算法来移动。

     

    1. #include
    2. void Hanoi(int n,char src,char mid,char dest)
    3. //将src座上的n个盘子,以mid座为中转,移动到dest座
    4. {
    5. if(n==1)//只需移动一个盘子
    6. {
    7. printf("%d %c->%c\n",n,src,dest);//直接将盘子从src移动到dest即可
    8. return;
    9. }
    10. else
    11. {
    12. Hanoi(n-1,src,dest,mid); //先将n-1个盘子从src移动到mid
    13. printf("%d %c->%c\n",n,src,dest);//再将一个盘子从src移动到dest
    14. Hanoi(n-1,mid,src,dest); //最后将n-1个盘子从mid移动到dest
    15. return;
    16. }
    17. }
    18. int main()
    19. {
    20. int n;
    21. scanf("%d",&n);
    22. Hanoi(n ,'A','B','C');
    23. return 0;
    24. }

    B.N皇后


    题目描述

    输入一个正整数N,则程序输出N皇后问题的全部摆法。输出结果里的每一行都代表一种摆法。行里的第i个数字如
    果是n,就代表第i行的皇后应该放在第n列。
    皇后的行、列编号都是从1开始算。

    输入

    4

    输出 

    1. 2 4 1 3
    2. 3 1 4 2

    题目解答

    用递归解决,一行一行的排查存在的可能性

    1. #include
    2. #include
    3. int N;
    4. int queenPos[100];//用来存放算好的皇后位置。最左上角是(0,0)
    5. void NQueen (int k)//在0~k-1行皇后已经摆好的情况下,摆第k行及其后的皇后
    6. {
    7. int i;
    8. if( k == N )// N 个皇后已经摆好
    9. {
    10. for( i=0 ;i
    11. {
    12. printf("%d ",queenPos[i]+1);
    13. }
    14. printf("\n");
    15. return;
    16. }
    17. for( i=0 ;i
    18. {
    19. int j;
    20. for( j=0 ;j//和已经摆好的 k 个皇后的位置比较,看是否冲突
    21. {
    22. if( queenPos[j] == i || fabs(queenPos[j]-i) == fabs(k-j) )
    23. break;//冲突,则试下一个位置
    24. }
    25. if( j == k )//当前选的位置 i 不冲突
    26. {
    27. queenPos[k] = i; //将第k个皇后摆放在位置 i
    28. NQueen(k+1);
    29. }
    30. }
    31. }
    32. int main()
    33. {
    34. scanf("%d",&N);
    35. NQueen(0); //从第0行开始摆皇后
    36. return 0;
    37. }

    C.波兰表达式


    题目描述

    波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的波兰表示法为+ 2 3。波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的波兰表示法为* + 2 3 4。本题求解波兰表达式的值,其中运算符包括+ - * /四个。

    输入

    输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。

    * + 11.0 12.0 + 24.0 35.0

    输出

    输出为一行,表达式的值。
    可直接用printf("%f\n", v)输出表达式的值v。

    1357.000000

    提示

    (11.0+12.0)*(24.0+35.0)

    题目解答

    1. #include
    2. #include
    3. double exp()//读入一个逆波兰表达式,并计算其值
    4. {
    5. char s[20];
    6. scanf("%s",s);
    7. switch(s[0])
    8. {
    9. case '+':
    10. return exp() + exp();
    11. break;
    12. case '-':
    13. return exp() + exp();
    14. break;
    15. case '*':
    16. return exp() * exp();
    17. break;
    18. case '/':
    19. return exp() / exp();
    20. break;
    21. default://输入的为数字直接进行运算
    22. return atof(s);
    23. break;
    24. }
    25. }
    26. int main()
    27. {
    28. printf("%lf",exp());
    29. return 0;
    30. }

    D.表达式求值


    题目描述

    求一个可以带括号的小学算术四则运算表达式的值

    输入

    一行,一个四则运算表达式。'*'表示乘法,'/'表示除法

    3.4
    7+8.3
    3+4.5*(7+2)*(3)*((3+4)*(2+3.5)/(4+5))-34*(7-(2+3))

    输出

    一行,该表达式的值,保留小数点后面两位

    3.40
    15.30
    454.75

    题目解答(x)

    表达式是个递归的定义

     

    1. #include
    2. #include
    3. #include
    4. int expression_value()//求一个表达式的值
    5. {
    6. int result = term_value();//求第一项的值
    7. bool more = true;
    8. while(more)
    9. {
    10. char op = cin.peek();//看一个字符,不取走
    11. if ( op == '+' || op == '-')
    12. {
    13. op =getchar();//从输入中取走一个字符
    14. int value = term_value();
    15. if( op == '+')
    16. result += value;
    17. else
    18. result -= value;
    19. }
    20. else
    21. more = false;
    22. }
    23. return result;
    24. }
    25. int term_value()//求一个项的值
    26. {
    27. int result = factor_value();//求第一个因子的值
    28. while(true)
    29. {
    30. char op =getchar();
    31. if( op == '*' || op == '/')
    32. {
    33. op = cin.peek();//看一个字符,不取走
    34. int value = factor_value();
    35. if( op == '*')
    36. result *=value;
    37. else
    38. result /=value;
    39. }
    40. else
    41. break;
    42. }
    43. return result;
    44. }
    45. int factor_value()
    46. {
    47. int result = 0;
    48. char c = cin.peek();//看一个字符,不取走
    49. if( c == '(')
    50. {
    51. c =getchar();
    52. result =expression_value();
    53. c =getchar();
    54. }
    55. else
    56. {
    57. while( isdigit(c) )
    58. {
    59. result = 10 * result + c - '0';
    60. c =getchar();
    61. c = cin.peek();//看一个字符,不取走
    62. }
    63. }
    64. return result;
    65. }
    66. int main()
    67. {
    68. printf("%d",expression_value() );
    69. return 0;
    70. }

    E.爬楼梯


    题目描述

    树老师爬楼梯,他可以每次走1级或者2级,输入楼梯的级数,求不同的走法数
    例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一级,第二次走两级
    也可以第一次走两级,第二次走一级,一共3种方法。

    输入

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

    1. 5
    2. 8
    3. 10

    输出

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

    1. 8
    2. 34
    3. 89

    题目解答

    n级台阶的走法 = 先走一级后,n-1级台阶的走法 + 先走两级后,n-2级台阶的走法
    f(n) = f(n-1) + f(n-2)

    边界条件: n < 0   0        n = 0  1        n = 1   1

                       n = 0   1        n = 1  1        n = 2   2

    1. #include
    2. int N;
    3. int stairs(int n)
    4. {
    5. if( n < 0)
    6. return 0;
    7. if( n == 0)
    8. return 1;
    9. return stairs(n-1) + stairs(n-2);
    10. }
    11. int main()
    12. {
    13. scanf("%d",&N);
    14. while(N)
    15. {
    16. printf("%d",stairs(N) );
    17. }
    18. return 0;
    19. }

    F.放苹果

    题目描述

    把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。

    输入

    第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。

    1. 1
    2. 7 3

    输出

    对输入的每组数据M和N,用一行输出相应的K。

    8

     题目解答

    设i个苹果放在k个盘子里放法总数是 f(i,k),则:

    k > i 时, f(i,k) = f(i,i)

    k <= i 时,总放法 = 有盘子为空的放法+没盘子为空的放法

    f(i,k) = f(i,k-1) + f(i-k,k)

    边界条件:没有苹果或者没有盘子;

    1. #include
    2. int f( int m,int n)
    3. {
    4. if( n > m)
    5. return f(m,m);
    6. else if( m == 0)
    7. return 1;
    8. else if( n <= 0)
    9. return 0;
    10. else
    11. return f(m,n-1) +f (m-n,n);
    12. }
    13. int main()
    14. {
    15. int t;
    16. scanf("%d",&t);
    17. while( t--)
    18. {
    19. int m,n;
    20. scanf("%d %d",&m,&n);
    21. printf("%d",f(m,n) );
    22. }
    23. return 0;
    24. }

  • 相关阅读:
    echarts实现折线图点击添加标记
    计算机毕业设计之java+javaweb的影院管理系统-电影院管理系统
    Golang 的三个核心调度模块:G、M 和 P
    springboot多数据源配置-通过SqlSessionFactory指定的数据源来操作指定目录的XML文件的方式
    嵌入式学习笔记(36)什么是定时器
    Llama2-Chinese项目:7-外延能力LangChain集成
    【脚本】【Linux】shell常用接口封装
    Springboot整合JavaMail(发送邮件)
    CTFHUB ICS(3)
    GaussDB数据库SQL系列-层次递归查询
  • 原文地址:https://blog.csdn.net/2301_80391227/article/details/136109238