Hm3
This commit is contained in:
194
Exercise/Homework3/Q1过了的版本.cpp
Normal file
194
Exercise/Homework3/Q1过了的版本.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
long long fastpow(long long d, long long u){
|
||||
//d^u<><75><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>
|
||||
long long result = 1, base = d, b = u;
|
||||
while(b > 0){
|
||||
if(b & 1) result *= base;
|
||||
base *= base;
|
||||
b >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int level(char c){
|
||||
switch(c){
|
||||
case '+':
|
||||
case '-': {
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case '*':
|
||||
case '/': {
|
||||
return 2;
|
||||
break;
|
||||
}
|
||||
case '^': {
|
||||
return 3;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int findexp(const string& s, int l, int r) {
|
||||
int pos = -1;
|
||||
int min_level = 114514;
|
||||
int js = 0;
|
||||
for (int i = r; i >= l; i--) {
|
||||
if (s[i] == ')') js--;
|
||||
else if (s[i] == '(') js++;
|
||||
|
||||
if (js == 0 && level(s[i])) {
|
||||
int lev = level(s[i]);
|
||||
if (lev < min_level || (lev == min_level && s[i] == '^')) {
|
||||
min_level = lev;
|
||||
pos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
long long toNum(const string& s, int l, int r) {
|
||||
long long tmp = 0;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD>
|
||||
while (l <= r && s[l] == ' ') l++;
|
||||
while (l <= r && s[r] == ' ') r--;
|
||||
|
||||
if (l > r) return 0;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
for (int i = l; i <= r; i++) {
|
||||
if (isdigit(s[i])) {
|
||||
tmp = tmp * 10 + (s[i] - '0');
|
||||
} else {
|
||||
return 0; // <20>Ƿ<EFBFBD><C7B7>ַ<EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
struct Node{
|
||||
char sign;
|
||||
long long num;
|
||||
Node* left;
|
||||
Node* right;
|
||||
|
||||
Node(): sign('?'), num(-1), left(nullptr), right(nullptr) {}
|
||||
Node(char s): sign(s), num(-1), left(nullptr), right(nullptr) {}
|
||||
Node(long long n): sign('?'), num(n), left(nullptr), right(nullptr) {}
|
||||
};
|
||||
|
||||
class Expression{
|
||||
public:
|
||||
string exp;
|
||||
Node* root;
|
||||
long long result;
|
||||
bool isValid;
|
||||
|
||||
Expression(const string& s): exp(s), root(nullptr), result(-1), isValid(true) {}
|
||||
|
||||
void inorder(Node* r){
|
||||
if(!r) return;
|
||||
inorder(r->left);
|
||||
if (r->sign == '?') cout << r->num;
|
||||
else cout << r->sign;
|
||||
inorder(r->right);
|
||||
}
|
||||
|
||||
Node* build(const string& s, int l, int r){
|
||||
//[l, r]
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD>
|
||||
while(l <= r && s[l] == ' ') l++;
|
||||
while(l <= r && s[r] == ' ') r--;
|
||||
if(l > r) return nullptr;
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><E2B2BF><EFBFBD><EFBFBD>
|
||||
if(s[l] == '(' && s[r] == ')'){
|
||||
bool hasQuote = true;
|
||||
int js = 0;
|
||||
for(int i = l; i <= r; i++){
|
||||
if(s[i] == '(') js++;
|
||||
else if(s[i] == ')') js--;
|
||||
|
||||
if(js == 0 && i != r){
|
||||
hasQuote = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasQuote) return build(s, l + 1, r - 1);
|
||||
}
|
||||
|
||||
int pos = findexp(s, l, r);
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if(pos == -1) {
|
||||
long long x = toNum(s, l, r);
|
||||
return new Node(x);
|
||||
}
|
||||
Node* tmp = new Node(s[pos]);
|
||||
tmp->left = build(s, l, pos - 1);
|
||||
tmp->right = build(s, pos + 1, r);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
long long calc(Node* r, bool& isValid){
|
||||
if(!r) return 0;
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
if(r->sign == '?') return r->num;
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
long long left = calc(r->left, isValid);
|
||||
long long right = calc(r->right, isValid);
|
||||
if(r->num == -1){
|
||||
char c = r->sign;
|
||||
switch(c){
|
||||
case '+': return left + right;
|
||||
case '-': return left - right;
|
||||
case '*': return left * right;
|
||||
case '/': {
|
||||
if(right == 0) {
|
||||
isValid = false;
|
||||
return 0;
|
||||
}
|
||||
else return left / right;
|
||||
}
|
||||
case '^': {
|
||||
return fastpow(left, right);
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void print(){
|
||||
inorder(root);
|
||||
}
|
||||
};
|
||||
|
||||
int main(){
|
||||
string s;
|
||||
while(getline(cin, s)){
|
||||
if (s.empty()) {
|
||||
cout << "INVALID" << endl;
|
||||
continue;
|
||||
}
|
||||
Expression tree(s);
|
||||
tree.root = tree.build(s, 0, s.length()-1);
|
||||
if (!tree.root) {
|
||||
cout << "INVALID" << endl;
|
||||
continue;
|
||||
}
|
||||
long long result = tree.calc(tree.root, tree.isValid);
|
||||
if(tree.isValid) cout << result << endl;
|
||||
else cout << "INVALID" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user