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
長度i | 1 | 2 | 3 | 4 |
---|---|---|---|---|
價格pi | 1 | 4 | 6.5 | 4 |
價格密度 | 1 | 2 | 6.5/3 | 1 |
按照貪心策略分割為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
1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|
6 | 2040 | 1950 | 1770 | 1860 | 1500 | 0 |
5 | 1930 | 2430 | 930 | 3000 | 0 | |
4 | 405 | 330 | 180 | 0 | ||
3 | 330 | 360 | 0 | |||
2 | 150 | 0 | ||||
1 | 0 |
最優化括號方案:
(\(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\j | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|
1 | 0 | 1 ! | 1 # | 1 ! | 1 ! | 1 # | 1 ! | 1 ! | 1 # |
0 | 1 ! | 1 @ | 2 ! | 2 # | 2 # | 2 ! | 2 # | 2 # | 2 ! |
0 | 1 ! | 1 @ | 2 ! | 2 @ | 2 @ | 3 ! | 3 # | 3 # | 3 ! |
1 | 1 @ | 2 ! | 2 # | 3 ! | 3 ! | 3 @ | 4 ! | 4 ! | 4 @ |
0 | 1 ! | 2 @ | 3 ! | 3 @ | 3 @ | 4 ! | 4 @ | 4 @ | 5 ! |
1 | 1 @ | 2 ! | 3 @ | 4 ! | 4 ! | 4 @ | 5 ! | 5 ! | 5 @ |
0 | 1 ! | 2 @ | 3 ! | 4 @ | 4 @ | 5 ! | 5 @ | 5 @ | 6 ! |
1 | 1 @ | 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.06 | 0.28 | 0.64 | |||||
0.06 | 0.3 | 0.7 | |||||
0.06 | 0.32 | ||||||
0.06 | 0.24 | ||||||
0.05 | 0.3 | ||||||
0.05 | 0.32 | ||||||
0.05 | 0.34 | ||||||
0.05 |
0.06 | 0.16 | 0.28 | 0.42 | 0.49 | 0.64 | 0.81 | 1 |
0.06 | 0.18 | 0.32 | 0.39 | 0.54 | 0.71 | 0.9 | |
0.06 | 0.20 | 0.27 | 0.42 | 0.59 | 0.78 | ||
0.06 | 0.13 | 0.28 | 0.45 | 0.64 | |||
0.05 | 0.2 | 0.37 | 0.56 | ||||
0.05 | 0.22 | 0.41 | |||||
0.05 | 0.24 | ||||||
0.05 |
1 | 1 | |||||
---|---|---|---|---|---|---|
2 | 2 | |||||
3 | 3 | |||||
4 | 4 | |||||
5 | 5 | |||||
6 | 6 | |||||
7 |
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)\)