forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
the-score-of-students-solving-math-expression.cpp
75 lines (70 loc) · 2.44 KB
/
the-score-of-students-solving-math-expression.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Time: O(n^3 * a^2)
// Space: O(n^2)
class Solution {
public:
int scoreOfStudents(string s, vector<int>& answers) {
static const int MAX_ANS = 1000;
const int n = (size(s) + 1) / 2;
vector<vector<unordered_set<int>>> dp(n, vector<unordered_set<int>>(n));
for (int i = 0; i < n; ++i) {
dp[i][i].emplace(s[i * 2] - '0');
}
for (int l = 1; l < n; ++l) {
for (int left = 0; left < n - l; ++left) {
const int right = left + l;
for (int k = left; k < right; ++k) {
for (const auto& x : dp[left][k]) {
for (const auto& y : dp[k + 1][right]) {
const int z = (s[2 * k + 1] == '+') ? x + y : x * y;
if (z <= MAX_ANS) {
dp[left][right].emplace(z);
}
}
}
}
}
}
const int target = evaluate(s);
int result = 0;
for (const auto& ans : answers) {
if (ans == target) {
result += 5;
} else if (dp.front().back().count(ans)) {
result += 2;
}
}
return result;
}
private:
int evaluate(const string& s) {
static const unordered_map<char, int> precedence = {{'+', 0}, {'*', 1}};
vector<int64_t> operands;
vector<char> operators;
int64_t operand = 0;
for (const auto& c : s) {
if (isdigit(c)) {
operands.emplace_back(c - '0');
} else {
while (!empty(operators) && precedence.at(operators.back()) >= precedence.at(c)) {
compute(&operands, &operators);
}
operators.emplace_back(c);
}
}
while (!empty(operators)) {
compute(&operands, &operators);
}
return operands.back();
}
template<typename T>
void compute(vector<T> *operands, vector<char> *operators) {
const auto right = operands->back(); operands->pop_back();
const auto left = operands->back(); operands->pop_back();
const char op = operators->back(); operators->pop_back();
if (op == '+') {
operands->emplace_back(left + right);
} else if (op == '*') {
operands->emplace_back(left * right);
}
}
};