POJ 1100

Dreisam Equations

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 3433   Accepted: 696

Description

During excavations in the Dreisamwuste, a desert on some far away and probably uncivilized planet, sheets of paper containing mysterious symbols had been found. After a long investigation, the project scientists have concluded that the symbols might be parts of equations. If this were true, it would be proof that the Dreisamwuste was civilized a long long time ago. 
The problem, however, is that the only symbols found on the sheets are digits, parantheses and equality signs. There is strong evidence that the people living in the Dreisamwuste knew only of three arithmetic operations: addition, subtraction, and multiplication. It is also known that the people of the Dreisamwuste did not have prioritization rules for arithmetic operations - they evaluate all terms strictly left to right. For example, for them the term 3 + 3 * 5 would be equal to 30, and not 18. 

But currently, the sheets do not contain any arithmetic operators. So if the hypothesis is true, and the numbers on the sheets form equations, then the operators must have faded away over time. 

You are the computer expert who is supposed to find out whether the hypothesis is sensible or not. For some given equations (without arithmetic operators) you must find out if there is a possibility to place +, -, and * in the expression, so that it yields a valid equation. For example, on one sheet, the string "18=7 (5 3) 2" has been discovered. Here, one possible solution is "18=7+(5-3)*2". But if there was a sheet containing "5=3 3", then this would mean that the Dreisamwuste people did not mean an equation when writing this.

Input

Each equation to deal with occupies one line in the input. Each line begins with a positive integer (less than 230) followed by an equality sign =. (For your convenience, the Dreisamwuste inhabitants used equations with trivial left sides only.) This is followed by up to 12 positive integers forming the right side of the equation. (The product of these numbers will be less than 230.) There might be some parentheses around groups of one or more numbers. There will be no line containing more than 80 characters. There is no other limit for the amount of the parentheses in the equation. There will always be at least one space or parenthesis between two numbers, otherwise the occurrence of white space is unrestricted. 

The line containing only the number 0 terminates the input, it should not be processed.

Output

For each equation, output the line "Equation #n:", where n is the number of the equation. Then, output one line containing a solution to the problem, i. e. the equation with the missing +, -, and * signs inserted. Do not print any white space in the equation. 

If there is no way to insert operators to make the equation valid, then output the line "Impossible". 

Output one blank line after each test case.

Sample Input

18 = 7 (5 3) 2
30 = 3 3 5
18 = 3 3 5
5 = 3 3
0

Sample Output

Equation #1:
18=7+(5-3)*2

Equation #2:
30=3+3*5

Equation #3:
Impossible

Equation #4:
Impossible

Hint

In case of mutiple answers, output the least one in order (+ < - < *).

Source

Mid-Central European Regional Contest 1999

大致题意:

在等式两边添加加、减、乘三种符号使两边相等。除括号外,三个符号的优先级相等。

解题思路:

将运算符和括号用数字代替,重新构造表达式。并使用完全三叉树(+-*)来构造

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;

//构造为表达式用到的代替数字
#define LEFT  -1    // 左括号
#define RIGHT -2    // 右括号
#define MUL   -3    // *
#define ADD   -4    // +
#define SUB   -5    // -
#define OP    -6    // 有运算符
#define NONE  -10

const int maxn = 100;
char a[maxn];   // 原始的等式数据
int b[maxn];    // 伪表达式
int best[maxn]; // 存储答案
int op[maxn];   // 运算符在数组b中的位置
int bn;         // 数组b的项数
int iLeft;      // 等号左边的数
int possible;   // 是否有解
int apos, bpos, opos;   // 位置指针

// 跳过空格
void skipSpace(){
    while(a[apos] && a[apos] == ' ') apos++;
}

int compute(); //前向声明,间接递归

//若有括号返回括号里面的值,否则返回当前数字
int bracket(){
    int sum;
    if(b[bpos] == LEFT){
        bpos++; // 跳过左括号
        sum = compute();    // 计算括号里面的值
        bpos++; // 跳过右括号
    }
    else sum = b[bpos++];    // 没有括号
    return sum;
}

//计算函数
int compute(){
    int sum = bracket(); //当前值
    while(b[bpos] == MUL || b[bpos] == ADD || b[bpos] == SUB){
        int operation = b[bpos++];     // 取出运算符
        int ret = bracket();    // 取下一个数
        switch(operation){
            case MUL: sum *= ret; break;
            case ADD: sum += ret; break;
            case SUB: sum -= ret; break;
        }
    }
    return sum;
}

void dfs(int dep){
    if(possible) return;
    // 所有的运算符构造完毕,判断等式是否成立
    if(dep == opos){
        bpos = 0;
        int iRight = compute();
        //等式成立
        if(iRight == iLeft){
            possible = 1;
            for(int i = 0; i < bn; ++i) best[i] = b[i];
        }
        return;
    }
    
    // Hint: 这里有顺序要求
    b[op[dep]] = ADD; dfs(dep + 1);
    b[op[dep]] = SUB; dfs(dep + 1);
    b[op[dep]] = MUL; dfs(dep + 1);

}

int main(){
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif // ONLINE_JUDGE

    int _ = 1;
    while(gets(a) && strchr(a, '='))//输入原等式并返回=的位置
     {
        possible = 0;
        for(int i = 0; i < maxn; ++i) b[i] = NONE;//初始化伪表达式
        apos = 0;//初始化原表达式指针
        sscanf(a, "%d", &iLeft);    // '='左边的数
        while(a[apos] && isdigit(a[apos])) apos++; //跳过左边数字
        skipSpace();//跳过空格
        apos++; //跳过 '='
        // 处理'='右边
        bn = 0;
        opos = 0;
        while(skipSpace(), a[apos]){
            if(a[apos] == '('){ // 左括号
                b[bn++] = LEFT;
                apos++;
                continue;
            }
            if(a[apos] == ')'){ // 右括号
                b[bn++] = RIGHT;
                apos++;
            }else{
                sscanf(a + apos, "%d", &b[bn++]);   // 读取数字
                while(a[apos] && isdigit(a[apos])) apos++; //跳过该数字
            }
            skipSpace();
            // 如果不是结尾和')',则有一个运算符
            if(a[apos] && a[apos] != ')'){
                op[opos++] = bn;
                b[bn++] = OP;
            }
        }

        dfs(0);
        printf("Equation #%d:\n", _++);
        if(!possible || !bn){
            printf("Impossible\n");
        }else if(bn == 1 && iLeft == b[0]){
            printf("%d=%d\n", iLeft, iLeft);
        }else{
            printf("%d=", iLeft);
            for(int i = 0; i < bn; ++i){
                switch(best[i]){
                    case ADD:   printf("+"); break;
                    case SUB:   printf("-"); break;
                    case MUL:   printf("*"); break;
                    case LEFT:  printf("("); break;
                    case RIGHT: printf(")"); break;
                    default :   printf("%d", b[i]); break;
                }
            }
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}

来自

https://blog.csdn.net/xushao_Movens/article/details/53088571

发布了158 篇原创文章 · 获赞 34 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_40421671/article/details/95061811