--- title: algorithm VI description: 第六次作業 --- # Group 2 組員:王承隆、賴文宏、施宗佑、王昱翔、王柏喬、莊淳方、傅文宗 # Problem 1(done) [CLRS 3 rd ] Exercise 15.2-1 - [x]完成[name=Joe] - [x]複查[name=Zongyou] ## Topic Find an optimal parenthesization of a matrix-chain product whose sequence of dimensions is $⟨5,10,3,12,5,50,6⟩$ ## Solution | | $A_2$ | $A_3$ | $A_4$ | $A_5$ | $A_6$ | | ----- |:----------- | ----------------- | ---------------------- | -------------------------- | --------------------------------- | | $A_1$ | $A_1A_2$<br>=150 | $(A_1A_2)A_3$<br>=330| $(A_1A_2)(A_3A_4)$<br>=405 | $(A_1A_2)(A_3A_4)A_5$<br>=1655 | $(A_1A_2)((A_3A_4)(A_5A_6))$=2010 | | $A_2$ | -------- | $A_2A_3$<br>=360 | $A_2(A_3A_4)$<br>=330 | $A_2((A_3A_4)A_5)$<br>=2430 | $A_2((A_3A_4)(A_5A_6))$<br>=1950 | | $A_3$ | -------- | -------- | $A_3A_4$<br>=180 | $(A_3A_4)A_5$<br>=930 | $(A_3A_4)(A_5A_6)$<br>=1770 | | $A_4$ | -------- | -------- | -------- | $A_4A_5$<br>=3000 | $A_4(A_5A_6)$<br>=1860 | | $A_5$ | -------- | -------- | -------- | -------- | $A_5A_6$<br>=1500 | $(A_1A_2)((A_3A_4)(A_5A_6))=2010為最佳解$ $(5*10)(10*3)(3*12)(12*5)(5*50)(50*6)$ $\rightarrow((5*10)(10*3))((3*12)(12*5)(5*50)(50*6))$ $\rightarrow((5*10)(10*3))(((3*12)(12*5))((5*50)(50*6)))$ ```c++= #include <iostream> #include <vector> #include <climits> using namespace std; void printSolution(vector<vector<int>> s, int i, int j){ if(i == j){ cout << "A" << i; return; } cout << '('; printSolution(s, i, s[i][j]); printSolution(s, s[i][j] + 1, j); cout << ')'; } //dim[0..n], m[1..n][1..n], s[1..n-1][2..n] void minimalMultiplication(vector<int> dim){ vector<vector<int>> m(dim.size(), vector<int> (dim.size(), 0)), s(dim.size(), vector<int> (dim.size(), 0)); int i, j, k, min; //the length of subproduct for(i = 2;i < dim.size();i++){ //left and right, jth to j + i - 1th matrix for(j = 1;j + i - 1 < dim.size();j++){ min = INT_MIN; //the minimum of calcutlation of i matrices for(k = j;k < i + j - 1;k++){ if(min > m[j][k] + m[k + 1][i + j - 1] + dim[j - 1]*dim[k]*dim[i + j - 1]){ min = m[j][k] + m[k + 1][i + j - 1] + dim[j - 1]*dim[k]*dim[i + j - 1]; s[j][i + j - 1] = k; } } m[j][i + j - 1] = min; } } printSolution(s, 1, dim.size() - 1); cout << " = " << m[1][dim.size() - 1] << endl; } int main(){ vector<int> dim; int n; while(cin >> n) dim.push_back(n); minimalMultiplication(dim); } ``` # Problem 2 ## 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 $\times$ 5. There are two ways to parenthesize the expression 2+(7$\times$ 5) = 37 and (2+7)$\times$ 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 ‘$\times$’. ## Solution ```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 //left and right, jth to j + i - 1th number for j from 0 to number.length()-i do max = INT_MIN //the maximum of calcutlation of i numbers for k from j to i+j-2 do 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; cin>>number_length; while(number_length--){ cin>>n; number.push_back(n); if(number_length!=0){ cin>>c; sign.push_back(c); } } maxvalue(number, sign); } ``` # Problem 3(done) [CLRS 3 rd ] Exercise 15.3-1 ## Topic Which is a more efficient way to determine the optimal number of multiplications in a matrix-chain multiplication problem: enumerating all the ways of parenthesizing the product and computing the number of multiplications for each, or running $RECURSIVE-MATRIX-CHAIN$? Justify your answer. ![](https://i.imgur.com/dOjF7PB.png) ## Solution Brute-force: $\Omega(\frac {4^n}{n^{\frac32}})$ from catalan number RECURSIVE−MATRIX−CHAIN: $\Theta (n^3)$ RECURSIVE−MATRIX−CHAIN is better. # Problem 4 [CLRS 3 rd ] Exercise 15.4-5 ## Topic Give an O(n^2)-time algorithm to find the longest monotonically increasing subsequence of a sequence of n numbers. ## Solution ``` Pseudocode longestIncSubseq(seq){ //seq is a array sorted[1..seq.size()] = seq sort(sorted) int i, j, counter int len[0..seq.size()][0..sorted.size()] = {} for i from 1 to seq.size() do for j from 1 to sorted.size()do if seq[i - 1] == sorted[j - 1] do len[i][j] = 1 + len[i - 1][j - 1] else if len[i - 1][j] > len[i][j - 1] do len[i][j] = len[i - 1][j] else len[i][j] = len[i][j - 1] end if end if end for end for stack sub counter = len[seq.size()][sorted.size()] i = seq.size() j = sorted.size() while i > 0 and j > 0 and counter > 0 do if counter == len[i - 1][j] do i-- else if(counter == len[i][j - 1]) do j-- else if(counter - 1 == len[i - 1][j - 1]) do sub.push_back(seq[--i]) j-- counter-- end if end while while(!sub.empty()) do print(sub.top()) sub.pop(); end while } ``` ```C++= #include <iostream> #include <vector> #include <stack> #include <algorithm> using namespace std; void longestIncSubseq(vector<int> seq){ vector<int> sorted = seq; sort(sorted.begin(), sorted.end()); int i, j, counter; int len[seq.size() + 1][sorted.size() + 1] = {}; for(i = 1;i <= seq.size();i++){ for(j = 1;j <= sorted.size();j++){ if(seq[i - 1] == sorted[j - 1]) len[i][j] = 1 + len[i - 1][j - 1]; else len[i][j] = len[i - 1][j] > len[i][j - 1] ? len[i - 1][j] : len[i][j - 1]; } } stack<int> sub; for(counter = len[seq.size()][sorted.size()], i = seq.size(), j = sorted.size();i > 0, j > 0, counter > 0;){ if(counter == len[i - 1][j]) i--; else if(counter == len[i][j - 1]) j--; else if(counter - 1 == len[i - 1][j - 1]){ sub.push(seq[i - 1]); i--; j--; counter--; } } cout << "longestIncSubseq:"; while(!sub.empty()){ cout << sub.top() << ' '; sub.pop(); } cout << endl; } int main(){ vector<int> seq; int n; while(cin >> n) seq.push_back(n); longestIncSubseq(seq); } ``` # Problem 5 [CLRS 3 rd ] Problem 15-5 Edit distance(要寫Code) ## Topic [題目連結](https://walkccc.github.io/CLRS/Chap15/Problems/15-5/) ```C++= // solution #include <bits/stdc++.h> #include <vector> using namespace std; string ops[7] = {"0", "C", "R", "D", "I", "T", "K"}; void ed(string str1, string str2, int cost[]) { int m = str1.length(), n = str2.length(); int dp[m+1][n+1], s[m+1][n+1] = {}; for(int i = 0;i<=m;i++) for(int j = 0;j<=n;j++) dp[i][j] = INT_MAX; dp[0][0] = -1; s[0][0] = -1; int temp; for(int i=0;i<=m;i++){ for(int j=0;j<=n;j++){ if(str1[i] == str2[j]) { dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j] + cost[0]); if(dp[i + 1][j + 1] == dp[i][j] + cost[0]) s[i + 1][j + 1] = 0; temp = 0; }else{ dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j] + cost[1]); if(dp[i + 1][j + 1] == dp[i][j] + cost[1]) s[i + 1][j + 1] = 1; temp = 1; } dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + cost[2]); if(dp[i + 1][j] == dp[i][j] + cost[2]) s[i + 1][j] = 2; dp[i][j + 1] = min(dp[i][j + 1], dp[i][j] + cost[3]); if(dp[i][j + 1] == dp[i][j] + cost[3]) s[i][j + 1] = 3; if(str1[i+1]==str2[j] && str1[j+1]==str2[i]){ dp[i + 2][j + 2] = min(dp[i + 2][j + 2], dp[i][j] + cost[4]); if(dp[i + 2][j + 2] == dp[i][j] + cost[4]) s[i + 2][j + 2] = 4; } dp[m][j] = min(dp[m][j], dp[i][j] + cost[5]); if(dp[m][j] == dp[i][j] + cost[5]) s[m][j] = 5; } } /* cout<<"\t "; for(int i=0;i<n;i++) cout<<i<<" "; cout<<"\n\n"; for(int i=0;i<=m;i++){ if(s>0) cout<<i-1<<"\t"; else cout<<"\n\t"; for(int j=0;j<=n;j++){ cout<<(s[i][j]==-1?"0":ops[1+s[i][j]])<<" "; } cout<<"\n"; } cout<<dp[m][n]<<"\n"; */ int M = m, N = n; m = 0; n = 0; while(m<=M&&n<=N){ int mc = m+1, nc = n+1; cout<<ops[(s[m][n]+1)]<<" "; //cout<<"\t"<<m<<", "<<n<<"\n"; if(s[m+1][n]<s[mc][nc]){ nc--; } if(s[m][n+1]<s[mc][nc]){ mc = m; nc = n+1; } m = mc; n = nc; } cout<<endl; } // Driver program int main() { // your code goes here string str1 ="sunday"; string str2 ="saturday"; // cin>>str1>>str2; int cost[6] = {1, 1, 1, 1, 1, 1}; //for(int i = 0;i<6;i++) // cin>>cost[i]; //cout<<str1<<"\t"<<str2<<endl; ed(str1, str2, cost); return 0; } ``` # Problem 6(done) ## Topic - [x] 完成[name=ZoneTwelve] [time=Thu, Apr 9, 2020 2:25 PM] - [x] 複查[name=Zongyou] [time=Thu, Apr 9, 2020 0:00 PM] Find out all **LCS** of《BADBCBA》and《ABACDBC》 ## Solution: | | | |L|C|S| | | | |-|-|-|-|-|-|-|-|-| | |∅|B|A|D|B|C|B|A| |∅|0| | | | | | | | |A|0| | | | | | | | |B| |1| | | | | | | |A| | |2| | | | | | |C| | | |2| | | | | |D| | | |3| | | | | |B| | | | |4| | | | |C| | | | | |5|5|5| Result: **BADBC** # Problem 7 String Alignment(要寫Code) ## Topic Let $\sigma$ be an alphabet set, $\beta$ denote the blank character in $\sigma$ , and a measure function F: $\sigma\times\sigma$ → R. Where F is defined as followings, for any x and y in $\sigma$ , F(x, y)<0 if x$\neq$y and F(x, y)>0 if x=y; whereas F( $\beta$ , $\beta$ )=-$\infty$. Given X and Y be two strings of $\sigma$ * , let X’ and Y’ denote two new strings made by inserting some $\beta$ into X and Y respectively. The similarity of X and Y is defined by measuring the maximal value of $\sum_{ a_i ∈X′, b_i ∈Y′} F(a_i , b_i )$ among all possible X’ and Y’. (a) Design an algorithm to find the similarity of X and Y. (b) Design an algorithm that describe where the blank characters are inserted to get the similarity. ## Solution (a, b一起) ``` Pseudocode stringAlignment(s1, s2, gap, dismatch, match){ //gap is the score of either s1[i] or s2[i] is space //m records maximal similarity of substrings of s1 and s2 int m[0..s1.length][0..s2.length], topLeft, left, top, max; //s records how we get the maximal similarity char s[0..s1.length][0..s2.length]; m[0][0] = 0; for i = 1 to s1.length do m[i][0] = m[i - 1][0] + gap; for i = 1 to s2.length do m[0][i] = m[0][i - 1] + gap; //constuct m and s for i = 1 to s1.length do for j = 1 to s2.length do if s1[i - 1] == s2[j - 1]; topLeft = m[i - 1][j - 1] + match; else topLeft = m[i - 1][j - 1] + dismatch; left = m[i][j - 1] + gap; top = m[i - 1][j] + gap; max = Max(topLeft, left, top); if max == topLeft s[i][j] = '↖'; else if max == top s[i][j] = '↑'; else if max == left s[i][j] = '←'; m[i][j] = max; end for end for //find s1' and s2' string s1' = "", s2' = ""; i = s1.length; j = s2.length; while(i > 0 || j > 0) if s[i][j] == '↖' s1' = s1[--i] + s1'; s2' = s2[--j] + s2'; else if s[i][j] == '↑' s1' = s1[--i] + s1'; s2' = ' ' + s2'; else if s[i][j] == '←' s1' = ' ' + s1'; s2' = s2[--j] + s2'; end while return m[s1.length][s2.length], s1', s2'; } ``` ```C++= #include <iostream> #include <vector> #include <iomanip> #include <tuple> using namespace std; int Max(int a, int b){ return a > b ? a : b; } void stringAlignment(string s1, string s2, int gap, int dismatch, int match){ int i, j, max, lu, l, u; vector<vector<tuple<int, int>>> len(s1.size() + 1, vector<tuple<int, int>>(s2.size() + 1, make_tuple(0, 0))); for(i = 1;i <= s1.size();i++) get<0>(len[i][0]) = get<0>(len[i - 1][0]) + gap; for(i = 1;i <= s2.size();i++) get<0>(len[0][i]) = get<0>(len[0][i - 1]) + gap; //get the length of longest subseq of length i from head for(i = 1;i <= s1.size();i++){ for(j = 1;j <= s2.size();j++){ lu = get<0>(len[i - 1][j - 1]) + (s1[i - 1] == s2[j - 1] ? match : dismatch); l = get<0>(len[i][j - 1]) + gap; u = get<0>(len[i - 1][j]) + gap; max = Max(lu, Max(l, u)); if(max == lu) get<1>(len[i][j]) = 0; else if(max == u) get<1>(len[i][j]) = 1; else if(max == l) get<1>(len[i][j]) = 2; get<0>(len[i][j]) = max; } } vector<char> s1b, s2b; for(i = s1.size(), j = s2.size();i > 1 || j > 1;){ switch(get<1>(len[i][j])){ case 0: s1b.push_back(s1[--i]); s2b.push_back(s2[--j]); break; case 1: s1b.push_back(s1[--i]); s2b.push_back(' '); break; default: s1b.push_back(' '); s2b.push_back(s2[--j]); } } switch(get<1>(len[i][j])){ case 0: s1b.push_back(s1[--i]); s2b.push_back(s2[--j]); break; case 1: s1b.push_back(s1[--i]); s2b.push_back(' '); break; default: s1b.push_back(' '); s2b.push_back(s2[--j]); } cout << endl << "similarity:" << get<0>(len[s1.size()][s2.size()]) << endl << "s1:"; for(i = s1b.size();i >= 0;i--) cout << s1b[i]; cout << endl << "s2:"; for(i = s2b.size();i >= 0;i--) cout << s2b[i]; cout << endl; } int main(){ string s1, s2; int gap, match, dismatch; cout << "s1:"; cin >> s1; cout << "s2:"; cin >> s2; cout << "scores" << endl << "gap:"; cin >> gap; cout << "match:"; cin >> match; cout << "dismatch:"; cin >> dismatch; stringAlignment(s1, s2, gap, dismatch, match); } ```