24h購物| | PChome| 登入
2013-08-11 22:20:13| 人氣1,717| 回應0 | 上一篇 | 下一篇

[UVA] 10906 - Strange Integration

推薦 0 收藏 0 轉貼0 訂閱站台

4th IIUC Inter-University Programming Contest, 2005

B

Strange Integration

Input: standard input
Output: standard output

Problemsetter: Md. Kamruzzaman

Do not get perplexed with the name of problem, it has nothing to do with integral calculus. We will concentrate on integration of simple algebraic expressions.

Complex algebraic expressions consisting of integers, addition and multiplication operators and parentheses can be represented by the following BNF notations –

<expr>   → <expr> + <term>
<expr>   → <term>
<term>   → <term> * <factor>
<term>   → <factor>
<factor> → (<expr>)
<factor> → num

According to the above grammar, both operators are left associative and multiplication is given higher precedence. So, 2 + 3*4 is same as 2 + (3*4). Similarly, 2 + 3 + 4 is same as (2+3) + 4. On the other hand, (2 + 3) * 4 is different to 2 + 3 * 4. It may be surprising but 2 + 3 + 4 is different to 2 + (3 + 4) as in this case, the order of evaluation is different.-

    2 + 3 + 4
=  5 + 4
=  9

    2 + (3 + 4)
=  2 + 7
=  9

Consider the expression (2+3)*4 + (2 +3)*5 + 6

The above picture depicts two different ways of representing the expression in hand if we follow the given grammar. The left one is known as the AST (Abstract Syntax Tree) and the other one is DAG (common sub-expression is handled once). Such a representation clearly shows the way of evaluating an algebraic expression. Here, each non-leaf node is assigned a unique variable name. As a result, we can have a sequence of simple expressions to evaluate the expression –

a = 2 + 3
b = a * 4
c = 2 + 3
d = c * 5
e = b + d
f = e + 6

a = 2 + 3
b = a * 4
d = a * 5
e = b + d
f = e + 6

In both cases, f denotes the original expression (2+3)*4 + (2+3)*5 + 6. Here, you have to integrate a sequence of simple expressions into the original one. A simple expression will always be of the form –

variable = (variable | integer)  (+ | *)  (variable | integer)

For a given sequence of simple expressions, there can be several original expressions. Consider the following cases –

a =  2 + 3
b =  a * 4
Then b can be -

b = (2 + 3) * 4
b = ((2 + 3) * 4)
b = ((2) + (3)) * 4
etc.

We need the first one, i.e. expression having minimum number of literals.

Input

The input file will start with an integer, T (1≤T≤100) denoting the number of tests. Each input will start with a positive integer, N (1≤N≤50) which is the number of simple expressions. Subsequent lines will contain the simple expressions defined above. The input will be valid, i.e. it will be always possible to construct a correct expression. Also, variable names will be referenced once they have been assigned. Either variable name or integers can have at most 10 characters. The integers will be always positive here (no unary minus) and variable names will contain letters only. Spaces will be used to separate numbers, variables and operators.

Output

For each input, print “Expression #D: “ followed by the expression denoted by the last variable in the list of simple expressions. Here D is the test number, starting from 1. The length of any expression will not be greater than 5000.

Sample Input

Output for Sample Input

2
2
A = 2 + 3
B = A + A
3
A = 2 + 3
B = A + 4
C = B + 5

Expression #1: 2+3+(2+3)
Expression #2: 2+3+4+5



題目描述對我來說有點困難,不過猜測之後得到 Accepted。
題目給定 BNF 語法以及目標 parse tree,為了要使 expression
藉由 BNF 任何一種 order of derivation 都可以得到唯一目標的 parse tree,
因此運算式要加上括弧。但要求輸出括弧最少,因此也就是長度最小的表達式。
需要觀察題目給定的 BNF,得到在何種情況下會有模稜兩可的分析。

走訪 parse tree 時,適時添加 "(exp)",每拜訪一個節點時,
相當於 subtree 也是一個最佳解,如此合併必然會形成最佳解。




#include <stdio.h>
#include <iostream>
#include <map>
using namespace std;
struct E {
    string lv, rv, op;
    E(string a, string b, string c):
        lv(a), op(b), rv(c) {}
    E():
        lv(""), op(""), rv("") {}
};
map<string, E> R;
string getLeft(string exp) {
    if(R.find(exp) == R.end())
        return "-1";
    return R[exp].op;
    int i, bracket = 0;
    for(i = exp.length()-1; i >= 0; i--) {
        if(exp[i] == ')')       bracket++;
        else if(exp[i] == '(')  bracket--;
        else {
            if(bracket == 0) {
                if(exp[i] == '*')
                    return "*";
                if(exp[i] == '+')
                    return "+";
            }
        }
    }
    return "-1";
}
string getRight(string exp) {
    if(R.find(exp) == R.end())
        return "-1";
    return R[exp].op;
    int i, bracket = 0;
    for(i = 0; i < exp.length(); i++) {
        if(exp[i] == ')')       bracket++;
        else if(exp[i] == '(')  bracket--;
        else {
            if(bracket == 0) {
                if(exp[i] == '*')
                    return "*";
                if(exp[i] == '+')
                    return "+";
            }
        }
    }
    return "-1";
}
string dfs(string nd) {
    E info = R[nd];
    string left, right;
    if(info.lv[0] < '0' || info.lv[0] > '9')
        left = dfs(info.lv);
    else
        left = info.lv;//integer
    if(info.rv[0] < '0' || info.rv[0] > '9')
        right = dfs(info.rv);
    else
        right = info.rv;//integer
    string l = getLeft(info.lv), r = getRight(info.rv);
    if(l == "-1" && r == "-1")
        return left + info.op + right;
    if(info.op == "+") {
        if(r == "-1" || r == "*")
            return left + "+" + right;
        return left + "+(" + right + ")";
    } else {
        if(l == "+" && (r == "+" || r == "*"))
            return "(" + left + ")*(" + right + ")";
        if(l == "+")
            return "(" + left + ")*" + right;
        if(r == "-1")
            return left + "*" + right;
        return left + "*(" + right + ")";
    }
}
int main() {
    int n, testcase, cases = 0;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d", &n);
        R.clear();
        char val[100], rv1[100], rv2[100], op[100];
        int i, j, k;
        for(i = 0; i < n; i++) {
            scanf("%s %*s %s %s %s", val, rv1, op, rv2);
            R[val] = E(rv1, op, rv2);
        }
        string ret = dfs(val);
        printf("Expression #%d: ", ++cases);
        cout << ret << endl;
    }
    return 0;
}

台長: Morris
人氣(1,717) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: UVA |
此分類下一篇:[UVA][二分greedy] 11920 - 0 s, 1 s and ? Marks
此分類上一篇:[UVA] 856 - The Vigenère Cipher

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文