--- tilte: program III --- > 放在這裡厲害了[name=Joe][color=#FF0000] > # Program III ## <i class="fa fa-user">ZoneTwelve</i> ```C++= #define INT_MAX 2147483647 #define INT_MIN -2147483647 - 1 #include <iostream> #include <string> #include <vector> #include <sstream> using namespace std; stringstream ss; class slice{ public: char o; int a, b, c, d, k; void apply(int A, int B, int C, int D){a=A;b=B;c=C;d=D;} void print(){cout<<a<<"\t"<<b<<"\t"<<c<<"\t"<<d<<"\t"<<k<<"\n";} }minPath[999][999], maxPath[999][999]; int len; int eval(int a, char op, int b) { switch(op){case '*':return a*b;case '+':return a+b;case '-':return a-b;} return 0; } int ups[999], dws[999]; void dfs(int y, int x, int c){ if(x==y)return; slice path = c==1?maxPath[y][x]:minPath[y][x]; if(y!=0)ups[y]++; if(x!=len&&y!=0)dws[x]++; switch(path.o){ case 'a': dfs(y, path.k, 0); dfs(path.k+1, x, 0); break; case 'b': dfs(y, path.k, 0); dfs(path.k+1, x, 1); break; case 'c': dfs(y, path.k, 1); dfs(path.k+1, x, 0); break; case 'd': dfs(y, path.k, 1); dfs(path.k+1, x, 1); break; } } int solution(vector<int> num, vector<char> sym) { len = num.size(); int minVal[len][len]; int maxVal[len][len]; for(int i = 0; i < len; i++){ for(int j = 0; j < len; j++){ minVal[i][j] = 999; // easy debug maxVal[i][j] = -999; minPath[i][j].o = -1; maxPath[i][j].o = -1; if(i == j){ minVal[i][j] = num[i]; maxVal[i][j] = num[i]; } } } for (int s = 0; s < len - 1; s++){ for (int i = 0; i < len - s - 1; i++){ int j = i + s + 1; int minval = INT_MAX; int maxval = INT_MIN; int chV = INT_MIN; int chI = -1; int maxK = INT_MIN, minK = INT_MAX; for (int k = i; k < j; k++ ){ int a = eval(minVal[i][k], sym[k], minVal[k + 1][j]); // like javascript eval(`${num}${op}${num}`); int b = eval(minVal[i][k], sym[k], maxVal[k + 1][j]); int c = eval(maxVal[i][k], sym[k], minVal[k + 1][j]); int d = eval(maxVal[i][k], sym[k], maxVal[k + 1][j]); //minPath[i][j].o = choose(0, a, b, c, d); //maxPath[i][j].o = choose(1, a, b, c, d); minPath[i][j].apply(minVal[i][k], minVal[k + 1][j], maxVal[i][k], maxVal[k + 1][j]); maxPath[i][j].apply(minVal[i][k], minVal[k + 1][j], maxVal[i][k], maxVal[k + 1][j]); minval = min(minval,min(a,min(b,min(c,d)))); maxval = max(maxval,max(a,max(b,max(c,d)))); if(maxval==a)maxPath[i][j].o = 'a'; if(maxval==b)maxPath[i][j].o = 'b'; if(maxval==c)maxPath[i][j].o = 'c'; if(maxval==d)maxPath[i][j].o = 'd'; if(minval==a)minPath[i][j].o = 'a'; if(minval==b)minPath[i][j].o = 'b'; if(minval==c)minPath[i][j].o = 'c'; if(minval==d)minPath[i][j].o = 'd'; if(maxK<maxval){ maxPath[i][j].k = k; maxK = maxval; } if(minK>minval){ minPath[i][j].k = k; minK = minval; } } minVal[i][j] = minval; maxVal[i][j] = maxval; } } for(int i=0;i<len;i++){ } dfs(0, len-1, 1); for(int i=0;i<len;i++){ for(int b=0;b<ups[i];b++) cout << '('; // cout << '('; cout << num[i] ; // cout << ')'; for(int b=0;b<dws[i];b++) cout << ')'; if(i+1<len) cout << sym[i]; } //cout << " = " << maxVal[0][len - 1] << endl; // return maxVal[0][len - 1]; } int main(){ int n; char s; string tmp; cin>>tmp; vector<int> num; vector<char> sym; ss<<tmp; ss>>n; num.push_back(n); for(int i=0;i<3;i++)if(incase[i]==tmp)testcase=i; while(!ss.eof()){ ss>>s; sym.push_back(s); ss>>n; num.push_back(n); } ss.clear(); solution(num, sym); } ``` # @jerrymark611 ``` pseudo= #include <iostream> #include <vector> #include <sstream> #include <climits> using namespace std; enum situation {MAX_MAX, MAX_MIN, MIN_MIN, MIN_MAX}; struct record{ int MAX ; int MIN ; situation MAX_case; situation MIN_case; }; record calculate( vector<int>number, vector<char>symbol, vector<vector<int>>Max, vector<vector<int>>Min, int l, int k, int r){ //calculate the value from l th to r th numbers' operation int a_MAX, a_MIN, b_MAX, b_MIN, MAX = INT_MIN, MIN = INT_MAX; situation MAX_stem, MIN_stem; //first operand if(l==k){ a_MAX = number[l]; a_MIN = number[l]; } else { a_MAX = Max[l][k]; a_MIN = Min[l][k]; } //second operand if(k+1==r) { b_MAX = number[r]; b_MIN = number[r]; } else { b_MAX = Max[k+1][r]; b_MIN = Min[k+1][r]; } switch (symbol[k]){ case '+': { if(a_MAX+b_MAX>MAX){ MAX = a_MAX+b_MAX; MAX_stem = MAX_MAX; } if(a_MAX+b_MIN>MAX){ MAX = a_MAX+b_MIN; MAX_stem = MAX_MIN; } if(a_MIN+b_MIN>MAX){ MAX = a_MIN+b_MIN; MAX_stem = MIN_MIN; } if(a_MIN+b_MAX>MAX){ MAX = a_MIN+b_MAX; MAX_stem = MIN_MAX; } if(a_MAX+b_MAX<MIN){ MIN = a_MAX+b_MAX; MIN_stem = MAX_MAX; } if(a_MAX+b_MIN<MIN){ MIN = a_MAX+b_MIN; MIN_stem = MAX_MIN; } if(a_MIN+b_MIN<MIN){ MIN = a_MIN+b_MIN; MIN_stem = MIN_MIN; } if(a_MIN+b_MAX<MIN){ MIN = a_MIN+b_MAX; MIN_stem = MIN_MAX; } return record{MAX, MIN, MAX_stem, MIN_stem}; case '-': { if(a_MAX-b_MAX>MAX){ MAX = a_MAX-b_MAX; MAX_stem = MAX_MAX; } if(a_MAX-b_MIN>MAX){ MAX = a_MAX-b_MIN; MAX_stem = MAX_MIN; } if(a_MIN-b_MIN>MAX){ MAX = a_MIN-b_MIN; MAX_stem = MIN_MIN; } if(a_MIN-b_MAX>MAX){ MAX = a_MIN-b_MAX; MAX_stem = MIN_MAX; } if(a_MAX-b_MAX<MIN){ MIN = a_MAX-b_MAX; MIN_stem = MAX_MAX; } if(a_MAX-b_MIN<MIN){ MIN = a_MAX-b_MIN; MIN_stem = MAX_MIN; } if(a_MIN-b_MIN<MIN){ MIN = a_MIN-b_MIN; MIN_stem = MIN_MIN; } if(a_MIN-b_MAX<MIN){ MIN = a_MIN-b_MAX; MIN_stem = MIN_MAX; } return record{MAX, MIN, MAX_stem, MIN_stem}; } case '*': { //MAX = a_MAX * b_MAX; if(a_MAX*b_MAX>MAX){ MAX = a_MAX*b_MAX; MAX_stem = MAX_MAX; } if(a_MAX*b_MIN>MAX){ MAX = a_MAX*b_MIN; MAX_stem = MAX_MIN; } if(a_MIN*b_MIN>MAX){ MAX = a_MIN*b_MIN; MAX_stem = MIN_MIN; } if(a_MIN*b_MAX>MAX){ MAX = a_MIN*b_MAX; MAX_stem = MIN_MAX; } if(a_MAX*b_MAX<MIN){ MIN = a_MAX*b_MAX; MIN_stem = MAX_MAX; } if(a_MAX*b_MIN<MIN){ MIN = a_MAX*b_MIN; MIN_stem = MAX_MIN; } if(a_MIN*b_MIN<MIN){ MIN = a_MIN*b_MIN; MIN_stem = MIN_MIN; } if(a_MIN*b_MAX<MIN){ MIN = a_MIN*b_MAX; MIN_stem = MIN_MAX; } return record{MAX, MIN, MAX_stem, MIN_stem};} } default: exit(1); } } void printSolution(vector<int> number, vector<char> symbol, vector<vector<int>> s, vector<vector<int>> Max, vector<vector<int>> Min, vector<vector<int>> leftMax, vector<vector<int>>rightMax, int l, int r, bool isMax, bool first){ int a,b; bool aMax, bMax; if(l==r) { cout<<number[l]; return; } int k ; if(isMax) { k = s[l][r]; if (leftMax[l][r]) // max get from left max operand { //a = Max[l][k]; aMax = true; } else { //a = Min[l][k]; // max get by left min operand aMax = false; } if (rightMax[l][r]) { //b = Max[k+1][r]; bMax = true; } else { //b = Min[k+1][r]; bMax = false; } } else { k = s[r][l]; if (leftMax[r][l]) // min get from left max operand { //a = Max[l][k]; aMax = true; } else { //a = Min[l][k]; // min get by left min operand aMax = false; } if (rightMax[r][l]) { //b = Max[l][k+1]; bMax = true; } else { //b = Min[l][k+1]; bMax = false; } } if(!first) cout << '('; if(aMax) printSolution(number, symbol, s, Max, Min, leftMax, rightMax, l, k, 1, 0); else printSolution(number, symbol, s, Max, Min, leftMax, rightMax, l, k, 0, 0); //if(isMax) cout << symbol[k]; //else // cout<<symbol[s[r][l]]; if(bMax) printSolution(number, symbol, s, Max, Min, leftMax, rightMax, k+1, r, 1, 0); else printSolution(number, symbol, s, Max, Min, leftMax, rightMax, k+1, r , 0, 0); if(!first) cout << ')'; return ; } //number[0..n-1], m[0..n-1][0..n-1], s[0..n-2][1..n-1] void maxvalue(vector<int> number, vector<char> symbol){ //m(number.size(), vector<int> (number.size(), 0)), vector<vector<int>> s(number.size(), vector<int> (number.size(), 0)); //position to cut vector<vector<int>> leftMax(number.size(), vector<int> (number.size(), 0)), rightMax(number.size(), vector<int> (number.size(), 0)); // choose max? vector<vector<int>> Max(number.size(), vector<int> (number.size(), INT_MIN)), Min(number.size(), vector<int> (number.size(), INT_MAX)); //values int max, min; record temp; for (int i=0 ;i< number.size();i++) for (int j=0 ;j< number.size();j++) if(i==j) { Max[i][j] = number[i]; Min[i][j] = number[i]; s[i][j] = -1; } if(number.size()==1){ cout<<'('<<number[0]<<") = "<<number[0]; return; } //length for(int l = 1;l < number.size();l++){ //left and right, jth to j + i - 1th number for(int i=0, j=l; i<number.size() && j<number.size(); i++, j++){ //the maximum of calcutlation of i numbers for(int k = i;k < j ;k++) //search the best location separate the formula { temp = calculate(number, symbol,Max, Min, i, k, j); //return a record of max and min if( Max[i][j] < temp.MAX) { Max[i][j] = temp.MAX; s[i][j] = k; if(temp.MAX_case==MAX_MAX) { leftMax [i][j] =1; rightMax [i][j] =1; } else if(temp.MAX_case==MAX_MIN) { leftMax [i][j] =1; rightMax [i][j] =0; } else if(temp.MAX_case==MIN_MAX) { leftMax [i][j] =0; rightMax [i][j] =1; } else { leftMax [i][j] =0; rightMax [i][j] =0; } } if(Min[i][j]> temp.MIN) { Min[i][j] = temp.MIN; s[j][i] = k; if(temp.MIN_case==MAX_MAX) { leftMax [j][i] =1; rightMax [j][i] =1; } else if(temp.MIN_case==MAX_MIN) { leftMax [j][i] =1; rightMax [j][i] =0; } else if(temp.MIN_case==MIN_MAX) { leftMax [j][i] =0; rightMax [j][i] =1; } else { leftMax [j][i] =0; rightMax [j][i] =0; } } } } } printSolution(number, symbol, s, Max, Min, leftMax, rightMax, 0, number.size()-1, 1, 1); cout<<" = "<<Max[0][number.size()-1]; } int main(){ string exp; cin>>exp; stringstream ss; ss<<exp; int i =0; char h; vector<int> number; vector<char> symbol; while(ss>>i){ number.push_back(i); ss>>h; symbol.push_back(h); } maxvalue(number, symbol); } ``` # program III ## topic A mathematical expression is given without parentheses. Design an algorithm to parenthesize the expression such that the value of the expression is maximized. For example, consider the expression: 2+7 * 5. There are two ways to parenthesize the expression 2+(7 * 5) = 37 and (2+7) * 5 = 45, so in this case, your algorithm should output the second expression. Here, you may assume the given expressions contain only 3 kinds of binary operators ‘+’, ‘-’, and ‘*’. Input: expression Ex: 2+7 * 5-3 * 6 Output: (((2+7)*5)-3)*6 or ((((2+7)*5)-3)*6) 1 <= expression's length <= 30 if there are several solutions, output one of them. ## Solution Time complexity: $O(n^3)$ //for there are triple nested for-loops using vector the outter loop: length of number the middle loop: start of index ``` Pseudocode calculate(number, sign, m, l, k, r) //number is an array of number, sign is an array of char [0 : n-1] //m is a 2-dimension array [0:n-1][0:n-1] //l is left bound index, r is right bound index //k is the index of the position to separate int a,b if l==k do a = number[l] else a = m[l][k] end if if k+1 == r d0 b = number[r] else b = m[k+1][r] end if if sign[k] == '+' do return a+b else if sign[k]=='-' do return a-b else if sign[k]== '*' do return a*b end if printSolution(number, sign, s, int i, int j){ //s is a 2-dimension array of solution [0:n-1][0:n-1] if i == j do print (number[i]); return end if print('(') printSolution(number, sign, s, i, s[i][j]); print(sign[s[i][j]]) printSolution(number, sign, s, s[i][j] + 1, j) print(')') } //number[0..n-1], m[0..n-1][0..n-1], s[0..n-2][1..n-1] maxvalue(number, sign){ number[0..n-1], sign[0..n-1][0..n-1], m[0..n-1][0..n-1], s[0..n-2][1..n-1] int i, j, k, max, num; //the length of numbers for i from 2 to number.size() do //O(n) //left and right, jth to j + i - 1th number for j from 0 to number.length()-i do //O(n) max = INT_MIN //the maximum of calcutlation of i numbers for k from j to i+j-2 do //O(n) num = calculate(number, sign, m, j, k, i+j-1) if max < num do max = num s[j][i + j - 1] = k end if end for m[j][i + j - 1] = max end for end for printSolution(number, sign, s, 0, number.size() - 1) print('='m[0][number.size() - 1]) } ``` ```c++= #include <iostream> #include <vector> #include <climits> using namespace std; int calculate( vector<int>number, vector<char>sign, vector<vector<int>> m, int l, int k, int r){ int a,b; if(l==k) a = number[l]; else a = m[l][k]; if(k+1==r) b = number[r]; else b = m[k+1][r]; switch (sign[k]){ case '+': return a+b; case '-': return a-b; case '*': return a*b; default: exit(1); } } void printSolution(vector<int> number, vector<char> sign, vector<vector<int>> s, int i, int j){ if(i == j){ cout << number[i]; return; } cout << '('; printSolution(number, sign, s, i, s[i][j]); cout << sign[s[i][j]]; printSolution(number, sign, s, s[i][j] + 1, j); cout << ')'; } //number[0..n-1], m[0..n-1][0..n-1], s[0..n-2][1..n-1] void maxvalue(vector<int> number, vector<char> sign){ vector<vector<int>> m(number.size(), vector<int> (number.size(), 0)), s(number.size(), vector<int> (number.size(), 0)); int i, j, k, max, num; //the length of numbers for(i = 2;i <= number.size();i++){ //left and right, jth to j + i - 1th number for(j = 0;j + i - 1 < number.size();j++){ max = INT_MIN; //the maximum of calcutlation of i numbers for(k = j;k < i + j - 1;k++){ num = calculate(number, sign, m, j, k, i+j-1); if(max < num){ max = num; s[j][i + j - 1] = k; } } m[j][i + j - 1] = max; } } printSolution(number, sign, s, 0, number.size() - 1); cout << " = " << m[0][number.size() - 1] << endl; } int main(){ vector<int> number; vector<char> sign; int n, number_length; char c; cout << "number of operands:"; cin>>number_length; cout << "expression:"; while(number_length--){ cin>>n; number.push_back(n); if(number_length!=0){ cin>>c; sign.push_back(c); } } maxvalue(number, sign); } ``` Test case: (1) Input: 5-8+7*4-8+9 ; Output: 5-((8+7)*(4-(8+9))) (2) Input: -11+22--11-22 ; Output: -11+(22-(-11-22)) (3) Input: 2-7*5+1-4+8*3 ; Output: 2-(7*(5+(1-((4+8)*3))))