递归(二)

递归(二)

例题:四则运算表达式求值

用递归解决递归形式的问题

例题: 四则运算表达式求值

输入为四则运算表达式,仅由整数、+、-、 * 、/ 、(、) 组成,没有空格,要求求其值。假设运算符结果都是整数 。"/"结果也是整数

解题思想:
表达式是个递归的定义:
image
image

因此对于表达式可以进行递归分析处理
代码如下:

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

int factor_value();

int term_value();

int expression_value();

int main() {
    cout << expression_value() << endl;
    return 0;
}

输入:(2+3)*(5+7)+9/3
输出: 63

int expression_value() //求一个表达式的值
{
    int result = term_value(); //求第一项的值
    bool more = true;
    while (more) {
        char op = cin.peek(); //看一个字符,不取走
        if (op == '+' || op == '-') {
            cin.get(); //从输入中取走一个字符
            int value = term_value();
            if (op == '+') result += value;
            else result -= value;
        } else more = false;
    }
    return result;
}

int term_value() //求一个项的值
{
    int result = factor_value(); //求第一个因子的值
    while (true) {
        char op = cin.peek();
        if (op == '*' || op == '/') {
            cin.get();
            int value = factor_value();
            if (op == '*')
                result *= value;
            else result /= value;
        } else
            break;
    }
    return result;
}

int factor_value() //求一个因子的值
{
    int result = 0;
    char c = cin.peek();
    if (c == '(') {
        cin.get();
        result = expression_value();
        cin.get();
    } else {
        while (isdigit(c)) {
            result = 10 * result + c - '0';
            cin.get();
            c = cin.peek();
        }
    }
    return result;
}

例题:爬楼梯

用递归将问题分解为规模更小的子问题进行求解

例题: 爬楼梯

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

例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一 级,第二次走两级,也可以第一次走两级,第二次走一级,一 共3种方法。

输入:
输入包含若干行,每行包含一个正整数N,代表楼梯技术,1 <= N <= 30 输出不同的走数法,每一行输入对应一行
输出
不同的走法数,每一行输入对应一行输出
样例输入

5
8
10

样例输出

8
34
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

通过边界条件防止无穷递归的发生

代码如下:

点击查看代码
#include <iostream>

using namespace std;
int N;

int stairs(int n) {
    if (n < 0)
        return 0;
    if (n == 0)
        return 1;
    return stairs(n - 1) + stairs(n - 2);
}

int main() {
    while (cin >> N) {
        cout << stairs(N) << endl;
    }
    return 0;
}

例题:放苹果

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

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

输出

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

样例输入

1
7 3

样例输出

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)

边界条件?

代码如下:

点击查看代码
#include <iostream>

using namespace std;

int f(int m, int n) {
    if (n > m)
        return f(m, m);
    if (m == 0)
        return 1;
    if (n <= 0)
        return 0;
    return f(m, n - 1) + f(m - n, n);
}

int main() {
    int t, m, n;
    cin >> t;
    while (t--) {
        cin >> m >> n;
        cout << f(m, n) << endl;
    }
    return 0;
}

例题:算24

n个数算24,必有两个数要先算。这两个数算的结果,和剩余n-2个数,就 构成了n-1个数求24的问题

枚举先算的两个数,以及这两个数的运算方式。

边界条件?

一个数算24

注意:浮点数比较是否相等,不能用==

代码如下:

点击查看代码
#include <iostream>
#include <cmath>

using namespace std;
double a[5];
#define EPS 1e-6

bool isZero(double x) {
    return fabs(x) <= EPS;
}

bool count24(double a[], int n) {//用数组a里的 n个数,计算24
    if (n == 1) {
        if (isZero(a[0] - 24))
            return true;
        else
            return false;
    }
    double b[5];
    for (int i = 0; i < n - 1; ++i)
        for (int j = i + 1; j < n; ++j) { //枚举两个数的组合
            int m = 0; //还剩下m个数, m = n - 2
            for (int k = 0; k < n; ++k)
                if (k != i && k != j)
                    b[m++] = a[k];//把其余数放入b
            b[m] = a[i] + a[j];
            if (count24(b, m + 1))
                return true;
            b[m] = a[i] - a[j];
            if (count24(b, m + 1))
                return true;
            b[m] = a[j] - a[i];
            if (count24(b, m + 1))
                return true;
            b[m] = a[i] * a[j];
            if (count24(b, m + 1))
                return true;
            if (!isZero(a[j])) {
                b[m] = a[i] / a[j];
                if (count24(b, m + 1))
                    return true;
            }
            if (!isZero(a[i])) {
                b[m] = a[j] / a[i];
                if (count24(b, m + 1))
                    return true;
            }
        }
    return false;
}

int main() {
    while (true) {
        for (int i = 0; i < 4; ++i)
            cin >> a[i];
        if (isZero(a[0]))
            break;
        if (count24(a, 4))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}
posted @ 2023-01-28 16:07  21MINM  阅读(9)  评论(0编辑  收藏  举报