华为机试:添加符号使等式成立

本文详细介绍了如何通过编程解决在特定数值等式左侧添加运算符以达成目标数值的问题,包括中缀到后缀表达式的转换、后缀表达式的计算以及通过枚举所有可能性来寻找满足条件的表达式个数。代码实现巧妙地运用了栈数据结构,展示了对表达式计算和转换的深入理解。
摘要由CSDN通过智能技术生成


题目描述:

输入一个正整数X,在下面的等式左边的数字之间添加+号或者-号或者不填,使得等式成立。

1 2 3 4 5 6 7 8 9 = X


比如:
12-34+5-67+89 = 5

1+23+4-5+6-7-8-9 = 5


请编写程序,统计满足输入整数的所有等式个数。


输入:       正整数,等式右边的数字

输出:       使该等式成立的个数


样例输入:5

样例输出:21


代码:

#include<iostream>
#include<string>
#include<stack>
#include<cmath>
using namespace std;

string inFixToPostFix(string expr)//简化的(没有*/和括号)中缀表达式转后缀表达式,细节见我的表达式计算博文,略有修改
{
    stack<char> opt;
    string res = "";
    int len = expr.size();
    for (int i = 0; i < len; i++)
    {
        if (isdigit(expr[i]))
        {
            res += expr[i];
        }
        else if(expr[i] == ' ')
        {
            continue;
        }
        else
        {
            if (i && isdigit(expr[i-1]))
            {
                res += ";";
            }
            if (opt.empty())
            {
                opt.push(expr[i]);
            }
            else
            {
                while (!opt.empty())
                {
                    res += opt.top();
                    res += ";";
                    opt.pop();
                }
                opt.push(expr[i]);
            }
        }
    }
    while(!opt.empty())
    {
        res += ";";
        res += opt.top();
        opt.pop();
    }
    res += ";";//这一句,是hack的做法,为了避免整个表达式就是123这种情况(没有操作符)
    return res;
}


int evalPostFix(string expr)//简化的后缀表达式计算
{
    int res = 0;
    stack<int> opr;
    int len = expr.size();
    int i, j;
    for (i = 0; i < len; i++)
    {
        if (expr[i] == ';')
        {
            continue;
        }
        else if (isdigit(expr[i]))
        {
            int num = 0;
            for (j = i; expr[j] != ';'; j++)//配合上面的;分割和结束判断
            {
                num = num * 10 + expr[j] - '0';
            }
            opr.push(num);
            i = j;
        }
        else
        {
            int right = opr.top();
            opr.pop();
            int left = opr.top();
            opr.pop();
            int t;
            switch(expr[i])
            {
            case '+':
                t = left + right;
                opr.push(t);
                break;
            case '-':
                t = left - right;
                opr.push(t);
                break;
            }
        }
    }
    res = opr.top();
    return res;
}

int main()
{
    string s = "1 2 3 4 5 6 7 8 9";
    int num;//等式右边的数字
    while(cin >> num)
    {
        int count = 0;//使等式成立的表达式个数
        int maxVaule = (int)pow(3, 8);//9个数字之间的8个位置,每个位置可以放置3种字符
        char select[] = " +-";//可选的字符列表
        for(int i = 0; i < maxVaule; i++)//枚举,把每个整数转化为相应的3进制数,然后改变等式左边的表达式
        {
            int t = i;
            for(int j = 1; j <= 15 ; j += 2)
            {
                s[j] = select[t%3];
                t /= 3;
            }
            if(evalPostFix(inFixToPostFix(s)) == num)//计算表达式的值
            {
                count++;
                cout << s << endl;
            }
        }
        cout << count << endl;
    }
    return 0;
}

结果:

当然,此题完全可以用DFS做,或者使用8重for循环计算,由于要求的是所有满足条件的等式个数,所以只能枚举,不可能更高效。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值