UVa 817 According to Bartjens Numeric Expression DFS ID Iterative Deepening Search Reverse Polish Expression

Question link: According to Bartjens
Question description:

Given a number consisting of numbers and a === string, you need to add+, −, ∗ +,-,*+,, Three symbols, while ensuring that the expression is legal (the new number formed at the same time cannot have leading zeros), makes the result of the expression equal to2000 20002000 , output all possible addition solutions (you must add at least one symbol), and output them in lexicographic order from small to large.
For example2100100 = 2100100=2100100The solution of = is as follows:
Insert image description here

answer:

This question only knows to add at least one symbol, so we need to enumerate and add one, two, three until n − 2 n-2n2 (nnn is the length of the expression), then useDFS DFSD FS tries to place a symbol at each position. When placing it, you need to pay attention to the fact that numbers containing leading zeros cannot appear. There are two ways to ensure that leading zeros do not appear:

  • Enumerate all positions, and in the final check, determine that the number that appears after the calculation symbol is 0 0Starts with 0 but has more digits than1 11
  • Make judgments during the search process, assuming that the position pos pos is foundp os if the current position is0 00 , then only non-numeric symbols can be placed after the current position;

How to evaluate an expression? Reverse Polish expressions can be used. Specifically, two stacks are used, one is used to save numbers and the other is used to save symbols. The priority of the symbols in the symbol station must be increased:

  • When a number is encountered, it is directly added to the number stack;
  • When a symbol is encountered, the priority of the symbol and the symbol on the top of the symbol stack is checked. If the priority of the symbol on the top of the stack is higher or equal, then the symbol on the top of the stack should be popped out for a calculation until the symbol stack is empty, or The symbol on the top of the stack has a lower priority, and then the current symbol is pushed onto the stack;
  • Finally, all symbols in the symbol stack are popped out and calculated in turn.

Code:

#include <bits/stdc++.h>

const int NaN = 0x3f3f3f3f;
const int OPERATOR_NUM = 3;

using namespace std;

int maxDepth, caseID;
string expression, now;
char ope[] = "*+-";
vector<string> ans;

// 比较两个运算符的优先级
int cmp(char op1, char op2)
{
    
    
    if (op1 == op2) {
    
     return 0; }
    if (op1 == '*') {
    
     return 1; }
    if (op2 == '*') {
    
     return -1; }
    return 0;
}

// 计算两个数的和、差或者积
int calculate(int lhs, char ope, int rhs)
{
    
    
    if (ope == '+') {
    
     return lhs + rhs; }
    if (ope == '-') {
    
     return lhs - rhs; }
    return lhs * rhs;
}

bool check()
{
    
    
    int num = NaN, lhs = 0, rhs = 0;
    stack<int> number;
    stack<char> ops;
    for (int i = 0; i < now.length() - 1; i++) {
    
    
        if (isdigit(now[i])) {
    
    
            if (num == NaN) {
    
     num = 0; }
            num = num * 10 + now[i] - '0';
        } else {
    
    
            number.push(num);
            while (!ops.empty() && cmp(ops.top(), now[i]) >= 0) {
    
    
                rhs = number.top(); number.pop();
                lhs = number.top(); number.pop();
                number.push(calculate(lhs, ops.top(), rhs));
                ops.pop();
            }
            ops.push(now[i]);
            num = NaN;
        }
    }
    if (num != NaN) {
    
     number.push(num); }
    while (!ops.empty()) {
    
    
        rhs = number.top(); number.pop();
        lhs = number.top(); number.pop();
        num = calculate(lhs, ops.top(), rhs); ops.pop();
        number.push(num);
    }
    return number.top() == 2000;
}

void dfs(int nowDepth, int pos)
{
    
    
    if (nowDepth == maxDepth) {
    
    
        int tempLen = now.length();
        int increment = expression.length() - pos;
        now.append(expression.substr(pos, increment));
        if (check()) {
    
     ans.push_back(now); }
        now.erase(tempLen, increment);
        return;
    }
    if (maxDepth - nowDepth > expression.length() - 2 - pos) {
    
     return; }
    for (int i = pos; i < expression.length() - 2; i++) {
    
    
    	// 这里是保证最后一个数字不含有前导零
        if (nowDepth == maxDepth - 1 && expression[i + 1] == '0' && expression[i + 2] != '=') {
    
     continue; }
        for (int j = 0; j < OPERATOR_NUM; j++) {
    
    
            int tempLen = now.length();
            int increment = i - pos + 1 + 1;
            now.append(expression.substr(pos, i - pos + 1));
            now.push_back(ope[j]);
            dfs(nowDepth + 1, i + 1);
            now.erase(tempLen, increment);
        }
        // 这里保证当前数字不含前导零,当前数字如果是以0开头那么不能继续进行拼接
        if (expression[pos] == '0') {
    
     break; }
    }
}

int main()
{
    
    
    while (cin >> expression) {
    
    
        ans.resize(0);
        now = "";
        if (expression[0] == '=') {
    
     break; }
        for (maxDepth = 1; maxDepth < expression.length() - 1; maxDepth++) {
    
     dfs(0, 0); }
        caseID++;
        cout << "Problem " << caseID << endl;
        sort(ans.begin(), ans.end());
        for (auto str : ans) {
    
     cout << "  " << str << endl; }
        if (ans.size() == 0) {
    
     cout << "  IMPOSSIBLE" << endl; }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45523675/article/details/129310788