15.1-1
T(n)=1+∑j=0n−1T(j)=1+T(0)+...+T(n−1)
T(n−1)=1+T(0)+...+T(n−2)
由上面两式得 T(n)=2T(n−1) ,通过数学归纳法可得 T(n)=2n
15.1-2
根据书中的数据,当长度为 4 的时候,每英寸的价值最高的是长度为 3 的时候,切割方案就是 3+1,得到的价值是 9。实际上不切割的价值也是 9,另外最好的切割方案是 2+2,此时的价值是 10 。
15.1-3
我们把自底向上的CUT-ROD
修改一下,先将
q
设置为没有切割时的价值,然后将第二个 for
改成 for i = 1 to j - 1
MODIFIED-CUT-ROD(p, n, c)
let r[0..n] be a new array
r[0] = 0
for j = 1 to n
q = p[j]
for i = 1 to j - 1
q = max(q, p[i] + r[j - i] + c)
r[j] = q
return r[n]
运行代码
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
//参数分别表示价格表,长度,固定成本,保存切割方案数组
int BOTTOM_UP_CUT_ROD(int *price,int n,int c,int *s)
{
int *r = new int[n+1];
*(r+0) = 0;
for(int j = 1; j <= n; ++j)
{
int q = *(price + j - 1);
*(s + j - 1) = j;
for(int i = 1; i < j; ++i)
{
int temp = *(price + i - 1) + *(r + j - i) - c;
if(q < temp)
{
q = temp;
*(s + j - 1) = i;
}
}
*(r + j) = q;
}
int ret = *(r + n);
delete []r;
return ret;
}
void PRINT_CUT_ROD_SOLUTION(int *s,int n)
{
while(n > 0)
{
cout << s[n-1] << ' ';
n -= s[n-1];
}
}
int main()
{
int p[] = {1,5,8,9,10,17,17,20,24,30};
int s[10];
memset(s,0,sizeof(int)*10);
for(int i = 1; i < 11; ++i)
{
cout << "Length " << i << "'s price is: " << BOTTOM_UP_CUT_ROD(p,i,0,s) << endl;
cout << "cut rod solution is: ";
PRINT_CUT_ROD_SOLUTION(s,i);
cout << endl;
}
return 0;
}
15.1-4
伪代码略,给出运行代码
#include <iostream>
#include <climits>
#include <cstring>
using std::cout;
using std::endl;
//参数分别表示价格表,长度,备忘机制数组r,保存切割方案数组
int MEMORIZED_CUT_ROD_AUX(int *price,int n,int *r,int *s)
{
if(n == 0)
return 0;
if(*(r + n -1) >= 0)
return *(r + n -1);
int q = INT_MIN;
for(int i = 0; i < n; ++i)
{
int temp = *(price + i) + MEMORIZED_CUT_ROD_AUX(price,n-i-1,r,s);
if(q < temp)
{
q = temp;
*(s + n - 1) = i + 1;
}
}
*(r + n - 1) = q;
return q;
}
int MEMORIZED_CUT_ROD(int *price,int n,int *s)
{
int *r = new int[n];
for(int i = 0; i < n; ++i)
*(r + i) = INT_MIN;
return MEMORIZED_CUT_ROD_AUX(price,n,r,s);
}
void PRINT_CUT_ROD_SOLUTION(int *s,int n)
{
while(n > 0)
{
cout << s[n-1] << ' ';
n -= s[n-1];
}
}
int main()
{
int p[] = {1,5,8,9,10,17,17,20,24,30};
int s[10];
memset(s,0,sizeof(int)*10);
for(int i = 1; i < 11; ++i)
{
cout << "Length " << i << "'s price is: " << MEMORIZED_CUT_ROD(p,i,s) << endl;
cout << "cut rod solution is: ";
PRINT_CUT_ROD_SOLUTION(s,i);
cout << endl;
}
return 0;
}
15.1-5
这个很简单,就直接写了,很显然是
FIBONACCI(n)
let fib[0..n] be a new array
fib[0] = fib[1] = 1
for i = 2 to n
fib[i] = fib[i-1] + fib[i-2]
return fib[n]
子问题图包括 n+1 个顶点 v0,v1,...,vn ,对 i=2,3,...,n ,顶点 vn 有两条边,分别指向顶点 vi−1,vi−2 。因此一共有 2n−2 条边。