一 动态规划的基本思想是将待求解问题分解成若干子问题(往往互不独立),最优子结构及子问题重叠性质是其基本要素。动态规划与分治法类似,但动态规划法避免耗费指数时间。
二 编程题(1)递归方程如下:
int DL(int a[], int b[],int n) {
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++)
{
if (a[j] < a[i]&& b[j]>b[i] - 1) {
b[i] = b[j] + 1;
}
}
}
int t = b[1];
for (int k = 0; k < n; k++)
{
if (b[k] > t) {
t = b[k];
}
}
return t;
}
其中b[]存放的是单调递增子序列的长度。
(a[j] < a[i]&& b[j]>b[i] - 1)该判断语句表示当仅当序列中前面的数小于后面的数并且b中存放的前面的大于后面的才有可能进行b数组中的数字交换。
编程题(2)递归方程如下:
int smallestFee(int start, int ende)
{
if(start + 1 == ende) //分解到只剩下2个站
{
p[start][ende] = r[start][ende];
mark[start][ende] = 1;
return r[start][ende];
}
p[start][ende] = r[start][ende]; //假设直接从start到ende为最小花费
int k, x1, x2;
for(k = start + 1; k < ende; ++k) //找从start到ende的最小花费
{
//计算过最小费用则不用再次计算
if(mark[start][k] != 1) x1 = smallestFee(start, k);
else x1 = p[start][k];
if(mark[k][ende] != 1) x2 = smallestFee(k, ende);
else x2 = p[k][ende];
if(p[start][ende] > x1 + x2)
p[start][ende] = x1 + x2;
}
mark[start][ende] = 1; //已经计算过标记为1
return p[start][ende];
}
解题的思路是,既然要得到最小的花费,那么就从最底层开始,逐层向上计算每两个站之间的最小花费,并记录在数组中,有记录的就不必再算了。其中两个站可能是相邻的,也可能不是相邻的。然后要得到方案,就需要对费用进行递归检测,比如:如果J、K两站之间的最小费用为M,但是J、K两站之间的某一站P满足:JP最小费用+PK最小费用等于JK最小费用,同时JK最小费用不等于由J直接到K的费用,则这个P站肯定是其中一个租船点。如果JK最小费用等于由J直接到K的费用,那么J和K必定是两个租船点,且其中没有租船点。在递归的过程中将这些租船点记录下来,就得到了最优方案。
三 结对编程
我和同伴都各自存在疑问。首先是对动态规划理解不深。以致于在拿到题时思路有点混乱。在交流想法之后先各自着笔,互相提出修改意见。通过对课程的学习,以及课后复习。我们对动态规划有了进一步的了解。