POJ 2252 - Equation Solver
http://poj.org/problem?id=2252
概要
与えられた EBNF に従った一次方程式が与えられるので,その解を答える.
ただし,解が無いときは「No solution.」と答え,解が無数にあるときは「Infinitely many solutions.」と答える.
制約
- 1つの式の長さは100文字未満.
- すべての部分式も一次式になる.つまり
x*x-x*x+x=0
のような入力は無い.
解法
構文解析しながら,一次式の加算・減算・乗算をするだけ.
poj/2252.cc1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 struct expr 6 { 7 int x, c; 8 expr(int a, int b) : x(a), c(b) {} 9 static expr var(int a) { return expr(a, 0); } 10 static expr lit(int a) { return expr(0, a); } 11 12 expr& operator+=(const expr& e) { x += e.x; c += e.c; return *this;} 13 expr& operator-=(const expr& e) { x -= e.x; c -= e.c; return *this;} 14 expr& operator*=(const expr& e) { x = x*e.c + e.x*c; c = c * e.c; return *this; } 15 }; 16 17 typedef string::const_iterator Iterator; 18 19 expr parse_expr(Iterator& it, const Iterator& last); 20 21 expr parse_factor(Iterator& it, const Iterator& last) 22 { 23 if (*it == '(') { 24 ++it; 25 const expr e = parse_expr(it, last); 26 ++it; 27 return e; 28 } else if (*it == 'x') { 29 ++it; 30 return expr::var(1); 31 } else if (isdigit(*it)) { 32 int n = 0; 33 while (it != last && isdigit(*it)) { 34 n = 10*n + *it-'0'; 35 ++it; 36 } 37 return expr::lit(n); 38 } else { 39 throw "parse error"; 40 } 41 } 42 43 expr parse_term(Iterator& it, const Iterator& last) 44 { 45 expr l = parse_factor(it, last); 46 while (it != last && (*it == '*')) { 47 ++it; 48 const expr r = parse_factor(it, last); 49 l *= r; 50 } 51 return l; 52 } 53 54 expr parse_expr(Iterator& it, const Iterator& last) 55 { 56 expr l = parse_term(it, last); 57 while (it != last && (*it == '+' || *it == '-')) { 58 const char op = *it; 59 ++it; 60 const expr r = parse_term(it, last); 61 if (op == '+') { 62 l += r; 63 } else { 64 l -= r; 65 } 66 } 67 return l; 68 } 69 70 int main() 71 { 72 string line; 73 for (int Ti = 1; getline(cin, line); Ti++) { 74 Iterator it = line.begin(), last = line.end(); 75 expr l = parse_expr(it, last); 76 if (it == last || *it != '=') { 77 throw "parse_error"; 78 } 79 ++it; 80 const expr r = parse_expr(it, last); 81 l -= r; 82 printf("Equation #%d\n", Ti); 83 if (l.x == 0) { 84 if (l.c == 0) { 85 puts("Infinitely many solutions."); 86 } else { 87 puts("No solution."); 88 } 89 } else { 90 printf("x = %.6f\n", double(-l.c)/l.x); 91 } 92 putchar('\n'); 93 } 94 return 0; 95 }