算法导论第十五章

it2022-05-08  14

15.1

15.1-1

证明:

​ T(n) = 1+\(\sum_0^{n-1}T(j)\)

​ 令S(n) = \(\sum_0^nT(j)\)

​ 则S(n) - S(n-1) = 1 + S(n-1)

​ S(n) = \(2^{n+1}\)-1

​ T(n) = \(2^n\)

15.1-2

长度i1234价格pi146.54价格密度126.5/31

按照贪心策略分割为3、1,总价格为7.5

然而最优解为2、2,总价格为8

15.1-3

#include <limits.h> int *solution(int *p, int n, int c) { int r[n+1]; r[0] = 0; for (int i = 1; i <=n; i++) { int q = INT_MIN; for (int j = 1; j <= i; j++) { q = max(q, p[j]+r[i-j]-c); } r[i] = q; } return r; }

15.1-4

#include <limits.h> void MEMORIZED_CUT_ROD_AUX(int *p, int n, int *r, int *s) { if (r[n] >= 0) { return r[n]; } if (n == 0) q = 0; else { q = INT_MIN; for (int i = 1; i <= n; i++) { int rest = MEMORIZED(p, n-i, r, s); if (q < p[i] + rest) { q = p[i] + rest; s[n] = i; } } r[i] = q; } return q; } void MEMOIZED_CUT_ROD(int *p, int n) { int r[n+1]; for (int i = 0; i <= n; i++) { r[i] = INT_MIN; } int s[n+1]; return MEMORIZED_CUT_ROD_AUX(p, n, r, s); }

15.1-5

int solution(int n) { int res[MAX_SIZE]; res[0] = 0; res[1] = 1; for (int i = 2; i <= n; i++) { res[i] = res[i-1]+res[i-2]; } return res[n]; }

15.2

15.2-1

12345662040195017701860150005193024309303000044053301800333036002150010

最优化括号方案:

(\(A_1\)\(A_2\))((\(A_3A_4\))(\(A_5A_6\)))

15.2-2

typedef struct { int matrix[MAX_SIZE][MAX_SIZE]; int n; int m; }Matrix; Matrix MATRIX_CHAIN_MUTIPLY(Matrix *a, int **s, int front, int rear) { if (front == rear) { return a[front]; } else { int p = s[front][rear]; Matrix t = MATRIX_CHAIN_MUTIPLY(a, s, front, p); Matrix y = MATRIX_CHAIN_MUTIPLY(a, s, p+1, rear); Matrix u; u.n = t.n; u.m = y.m; for (int i = 0; i < t.n; i++) { for (int j = 0; j < t.m; j++) { for (int k = 0; k < t.m; k++) { u.matrix[i][k] += t.matrix[i][j]*y.matrix[j][k]; } } } return u; } }

#### 15.2-3

证明:

设P(k) >= \(c2^k\)

P(n) = \(\sum_1^{n-1}\)P(k)P(n-k)

\(\geq\)\(\sum_1^{n-1}c2^k*c2^{n-k}\)

\(\geq\)\(\sum_1^{n-1}c^22^n\)

\(\geq\)\(c2^n\)

15.2-4

\(\frac{n^2-n}{2}\)个顶点,2(n-2)条边,分别连接顶点(1, i)、(i+1, n)(i = 2,3,4,...,n-1)

15.2-5

由条件。只有计算m(a, b)(a<i, b=j或者a = i, b >j)时才会访问m(i, j)

所以R(i,j) = i-1+n-j = n+i-j-1(j > i)

所以\(\sum_1^n\)\(\sum_1^n\)R(i,j) = \(\frac{n^2-n}{2}\)\((n-1)\)+\(\sum_1^ni*(n-i)\)-\(\sum_2^{n-1}\)\(\frac{(n-j+1)(j+n)}{2}\)

​ = \(\frac{n^3-n}{3}\)

15.2-6

证明:

显然,当n=2时结论成立。

假设当n=k时结论也成立,

则当n=k+1时,

\(N_k\)为n=k时的表达式,则\(N_{k+1} = (N_k*A_{k+1})\)

则n+1时,结论也成立。

15.3

15.3-1

第二种,原因: 显然A[1],...,A[n]的每一种排列都是一种可能的括号化方案,则T(n) = \(\Omega\)(n!)

而第二种T(n) = \(\Omega\)(\(\frac{4^n}{n^{3/2}}\)) < \(\Omega\)(n!)

15.3-2

因为MERGE_SORT在递归的每一步都生成全新的子问题

15.3-3

具有最优子结构的性质

15.3-4

输入序列为:<5,10,15,20>

根据Capulet的观点,

由于\(5*10*20\) < \(5*15*20\)

最优解为\(A_1(A_2A_3)\)

实际上最优解为\((A_1A_2)A_3\)

15.3-5

证明:只需举反例即可。

构造如下:将长度为x的钢条切割的最优解为k,x-k。

其中k与x-k的结构中都切割出长度为i的钢条至少\(\frac{l^i/2+1}{2}\)次。则与题目矛盾。

15.3-6

if \(c_k = 0\)

\(W_{1,k}\)为从货币1兑换到货币k的最大收益。

则$W_{1,n} $ = \(max_{1\leq i \leq n-1}\){\(W_{1,i}*r_{i,n}\)}

由此递归式可求结果。


if \(c_k\)为任意值:

\(L_{1,k}\)为从从货币1兑换到货币k由最大收益时的兑换次数

则$W_{1,n} $ = \(max_{1\leq i \leq n-1}\){\(W_{1,i}*r_{i,n}-c_{L_{1,i}+1}\)}

由于\(c_k\)的值不确定,无法确定是否具有最优子结构

\(c_k\)是一个广义单调函数,则子问题仍具有最优子结构

15.4

15.4-1

i\j010110110101 !1 #1 !1 !1 #1 !1 !1 #01 !1 @2 !2 #2 #2 !2 #2 #2 !01 !1 @2 !2 @2 @3 !3 #3 #3 !11 @2 !2 #3 !3 !3 @4 !4 !4 @01 !2 @3 !3 @3 @4 !4 @4 @5 !11 @2 !3 @4 !4 !4 @5 !5 !5 @01 !2 @3 !4 @4 @5 !5 @5 @6 !11 @2 !3 @4 !5 !5 @6 !6 !6 @

一个LCS:100110

15.2-4

void printLCS(int *c, char *s, char *t, int i, int j) { if (i == 0 or j == 0) { printf("\n"); return; } if (s[i] == t[j]) { printf("%c ", s[i]); } else { if (c[i-1][j] >= c[i][j-1]) { printLCS(c, s, t, i-1, j); } else { printLCS(c, s, t, i, j-1); } } }

#### 15.4-3

for (int i = 0; i <= s.size(); i++) { for (int j = 0; j <= t.size(); j++) { c[i][j] = 0; } } void LCS_LENGTH(char *s, char *t, int *c, char *b, int i, int j) { if (i == 0 || j == 0) { return; } if (s[i-1] == t[j-1]) { if (c[i-1][j-1] == 0) LCS_LENGTH(s, t, c, b, i-1. j-1); c[i][j] = c[i-1][j-1]+1; b[i][j] = '!'; } else { if (c[i-1][j] == 0) LCS_LENGTH(s, t, c, b, i-1, j); if (c[i][j-1] == 0) LCS_LENGTH(s, t, c, b, i, j-1); if (c[i-1][j] >= c[i][j-1]) { b[i][j] = '@'; c[i][j] = c[i-1][j]; } else { b[i][j] = '#'; c[i][j] = c[i][j-1]; } } }

#### 15.4-4

int LCS_LENGTH(char *s, char *t) { m = s.length; n = t.length; if (m < n) { int tmp = m; m = n; n = m; char *_tmp = s; s = t; t = _tmp; } int c[2][n+1]; for (int i = 0; i < 2; i++) { for (int j = 0; j <= n; j++) { c[i][j] = 0; } } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s[i-1] == t[j-1]) { c[i%2][j] = c[(i-1)%2][j-1]+1; } else { c[i%2][j] = max(c[(i-1)%2][j], c[i%2][j-1]); } } } return c[m%2][n]; }
int LCS_LENGTH(char *s, char *t) { m = s.length; n = t.length; if (m < n) { int tmp = m; m = n; n = m; char *_tmp = s; s = t; t = _tmp; } int c[n]; int temp = 0; for (int i = 0; i < n; i++) { c[i] = 0; } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (s[i] == t[j]) { int tmp = c[j]; c[j] = temp+1; temp = tmp; } else { temp = c[j]; c[j] = max(c[j-1], c[j]); } } } return c[n-1]; }

15.4-5

void LONGEST_INCREASE_SEQUENCE(int *x, int *c, int *b) { int n = a.length(); int y[n]; for (int i = 0; i < n; i++) y[i] = x[i]; quick_sort(y, <); LCS_LENGTH(x, y, c, b); }

15.4-6

#include <limits.h> int n = x.length(); int d[n]; int g[n]; for (int i = 0; i < n; i++) { g[i] = INT_MAX; } void LIS(int *x) { d[0] = 1; g[d[0]] = x[0]; int length = 1; for (int i = 1; i < n; i++) { int k = binary_search_geq(x, x[i]); if (k == -1) { d[i] = d[i-1]+1; g[d[i]] = x[i]; if (d[i] > length) { length = d[i]; } } else { d[i] = k; g[k] = x[i]; if (d[i] > length) { length = d[i]; } } } for (int i = 1; i <= length; i++) { printf("%d ", g[i]); } }

d[i]表示以x[i]为结尾的候选子序列的最长长度,g[i]表示最长长度为i的候选子序列的结尾元素。

由条件最长候选子序列的长度为\(max_{1\leq i \leq n}\){d[i]}

而g[i]满足题目中给出的提示,即g[i] < g[j] (i < j) ,且g[1],...,g[length]组成一个LIS

15.5

15.5-1

void CONSTRUCT_OPTIMAL_BST(int *root, int i, int j) { if (i > j) { return; } int q = root[i][j]; CONSRTUCT_OPTIMAL_BST(root, i, q-1); printf("%d", q); CONSTRUCT_OPTIMAL_BST(root, q+1, j); }

15.5-2

0.060.280.640.060.30.70.060.320.060.240.050.30.050.320.050.340.05 0.060.160.280.420.490.640.8110.060.180.320.390.540.710.90.060.200.270.420.590.780.060.130.280.450.640.050.20.370.560.050.220.410.050.240.05 1122334455667

use computer to solve it

15.5-3

时间复杂度为\(\Theta(n^4)\)

15.5-4

由于root[i,j-1] \(\leq\)root[i,j]\(\leq\)root[i+1,j]

所以for (r = i to j)减少为for (r = root[i,j-1] to root[i+1,j])为不大的一个常数次

实际上,root的值可以单独计算,而不是在最里层的循环中,

具体计算顺序为:沿着主对角线从左下向右上依次计算。

总计算次数为\(\sum_i\)\(\sum_j root[i+1][j]-root[i][j-1]+1\) = \(\sum_kroot[k,1]-root[1,k]+n-k\) = \(\Theta(n^2)\)

转载于:https://www.cnblogs.com/KarlZhang/p/8490579.html

相关资源:算法导论第十五章习题解答

最新回复(0)