John has never been very good at maths. Due to his bad grades, his parents have sent him to the
Academic Coalition of Mathematics (ACM). Despite the large amount of money his parents are spending
on the ACM, John does not pay much attention during classes. However, today he has begun to think about
all the effort his parents are putting into his education, and he has started to feel somewhat...
guilty. So he has made a decision: he is going to improve his maths grades!
However, no sooner had he resolved to pay attention than the lesson
ended. So the only
thing he has been able to do is to hurriedly copy the content of the
blackboard in his notebook.
Today, the teacher was explaining basic arithmetic expressions with
unknowns. He vaguely remembers
that his classmates have been substituting values into the unknowns to
obtain the expressions' results. However, in all the hurry,
John has only written down expressions, values and results in a messy
fashion. So he does not know which value comes with each unknown,
or which result goes with each expression.
That is the reason he needs your help: he wants to know, given an
expression, some values and a
result, whether it is possible or not to assign those values to the
unknowns in order for the
expression to evaluate to the given result. The particular assignment of
values does not matter to John, as he wants to do it by himself.
He only wants to know whether it is possible or not.
Each test case in the input file consists of two lines:
- The first line contains a sequence of natural numbers. The first one (
1n 5) is the
number of unknowns that will occur in the expression. It is followed by a sequence of n integers
v1...vn (
0 vi 50), which are the values to be assigned to the unknowns. Finally, there is
an integer m (
0 m 1000) representing the desired result of the evaluation of the expression.
- The second line contains an arithmetic
expression composed of lowercase letters (a-z), brackets (( and )) and binary
operators (+, -, *). This expression will contain n unknowns, represented by
n different lowercase letters, without repetitions. The expression will not contain any blanks and will always be
syntactically correct, i.e. it is just an unknown or has the form (e1 op e2
), where e1 and e2 are expressions and op is one of the three possible binary
operators.
The input will finish with a dummy test case of just one line containing 0 0, which must not be processed.
For each test case, print a single line with YES if there exists an assignment of the values
v1 ...vn to the unknowns such that the expression evaluates to m, and NO otherwise. Notice that each value vi
must be assigned to exactly one unknown.
3 2 3 4 14
((a+b)*c)
2 4 3 11
(a-b)
1 2 2
a
0 0
YES
NO
YES
中轉後,窮舉 assign 的排列 n !,接著計算後序確認。
#include <iostream>
#include <sstream> // stringstream
#include <ctype.h> // isdigit()
#include <stdio.h>
#include <algorithm>
using namespace std;
//<stack template>
template <typename T>
struct Node {
T d;
Node *prev;
};
template <class T>
class STACK { // linked list implements stack
public:
STACK() {
idx = NULL;
SIZE = 0;
}
T top() {
T cpy = idx->d;
return cpy;
}
void pop() {
Node<T> *tmp;
tmp = idx;
idx = idx->prev;
delete tmp;
SIZE--;
}
void push(T item) {
Node<T> *nd = new Node<T>;
nd->d = item;
nd->prev = idx;
idx = nd;
SIZE++;
}
bool empty() {
return idx == NULL;
}
int size() {
return SIZE;
}
private:
Node<T> *idx;
int SIZE;
};
//</stack template>
//<parse infix>
int priority(char c) {
switch(c) {
case '(':return 1;
case '+':return 2;
case '-':return 2;
case '*':return 3;
}
return -1; // error state
}
string infix2postfix(string infix) {
string postfix = "";
int i, j, len = infix.length();
STACK<char> opStk; // save operator, not number
for(i = 0; i < len; i++) {
if(infix[i] == ' ')
continue;
if(isdigit(infix[i]) || isalpha(infix[i])) { // cut number
while(i < len && (isdigit(infix[i]) || isalpha(infix[i]))) {
postfix += infix[i];
i++;
}
i--; // because for loop i++
postfix += ' ';
} else { // operator or '(' or ')'
if(infix[i] == ')') {
while(opStk.top() != '(') {
postfix += opStk.top();
postfix += ' ';
opStk.pop();
}
opStk.pop(); // pop '('
} else {
while(!opStk.empty() && infix[i] != '(') {
if(opStk.top() != '(') {
if(priority(opStk.top()) >= priority(infix[i])) {
postfix += opStk.top();
postfix += ' ';
opStk.pop();
} else
break;
} else
break;
}
opStk.push(infix[i]);
}
}
}
while(!opStk.empty()) {
postfix += opStk.top();
postfix += ' ';
opStk.pop();
}
return postfix;
}
//</parse infix>
//<calc postfix>
int assign_val[26];
int calcPostfix(string postfix) {
STACK<int> stk;
stringstream sin(postfix);
string token;
int a, b;
while(sin >> token) {
switch(token[0]) {
case '+': case '-': case '*':
b = stk.top(), stk.pop();
a = stk.top(), stk.pop();
if(token == "+")
stk.push(a+b);
if(token == "-")
stk.push(a-b);
if(token == "*")
stk.push(a*b);
break;
default:
a = assign_val[token[0]-'a'];
stk.push(a);
}
}
return stk.top();
}
//</calc postfix>
int main() {
int n, m, i, j, v[10];
string infix, postfix;
while(scanf("%d", &n) == 1 && n) {
for(i = 0; i < n; i++)
scanf("%d", &v[i]);
scanf("%d", &m);
while(getchar() != '\n');
getline(cin, infix);
postfix = infix2postfix(infix);
int unknown_val[26] = {}, postfix_len = postfix.length();
for(i = 0; i < postfix_len; i++) {
if(isalpha(postfix[i])) {
unknown_val[postfix[i]-'a'] = 1;
}
}
for(i = 0, j = 0; i < 26; i++) {
if(unknown_val[i])
unknown_val[j++] = i;
}
int flag = 0;
do {
for(i = 0; i < n; i++)
assign_val[unknown_val[i]] = v[i];
long long calc_ans = calcPostfix(postfix);
if(calc_ans == m)
flag = 1;
} while(!flag && next_permutation(unknown_val, unknown_val+n));
puts(flag ? "YES" : "NO");
}
return 0;
}
文章定位: