西电软件学院算法实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第二次试验
一、
问题:
Matrix-chain product
分析:
本题是矩阵链乘问题,需要求出最优括号化方案。即在矩阵的乘法链上添加括号来改变运算顺序以使矩阵链乘法的代价降低。
可以分析该链乘的一个子段总结一些结论。假设m[i,j]表示A i*…*A j的链成需要进行的乘法次数(假设j-i足够大),我们可以将A i*…*A j分为两段进行计算:(A i*…*A k)*(A k+1*…*A j)可以得出m[i,j]的递推公式
可以得出,当i=j的时候,m[i,j]=0。当i 可以根据上式得到一个递归算法。本题即是求m[1,n]的值。 用二维数组m存储m[i,j]的值,用二维数组s来储存应当分割的位置。 以本题中第一个矩阵a) <3, 5, 2, 1,10>为例,可以得出如下矩阵: 通过m数组可以得出最少的乘法次数,通过s数组可以输出最优方案。 遇到的问题: 在输出s数组的结果的时候仍然需要递归调用,需要合适的控制递归的条件。 总结: 在矩阵链乘问题中可以看出,动态规划结合递归的思想可以快捷的解决很多问题。本题中,重点是归纳出m[i,j]的递推公式。 二、 问题: Longest Common Subsequence 分析: 本题即是最长公共子序列问题。假设有序列A[m]和序列B[n],显然,对于每一个[i,j],都对应着一个公共子序列的长度。假设长度为c,就可以得到一个二维数组c[m,n]。对于c[i,j],当Ai=Bj的时候,问题就转变为求A[1..i-1]和B[1..j-1]的公共子序列长度的问题,所以c[i,j]的长度就是c[i-1,j-1] + 1; 同理,当Ai != Bj的时候,c[i,j]应该在c[i-1,j]与c[i,j-1]中取最大值。另外,当i或者j等于0的时候,显然c的值为0。由上面所述,可以得到递推公式如下: 为了解决这个问题,还如要定义另一个数组用于存放c数组中每一个元素的来源。这个来源其实就反映了公共子串。可以通过箭头表示来源,相连的箭头序列中指向左上方的箭头最多的一串对应的就是最长公共子序列。 比如对于题目中给出的第一个例子 X: xzyzzyx Y: zxyyzxz 可以用一个矩阵表示计算的过程: 遇到的问题: 在算法中,‘=’是属于‘<’还是‘>’会给结果带来不同。在输出子序列的时候,最长公共子序列可能不止一个,但是最终未能解决还是只能输出一个。 总结: 最长公共子序列问题可以利用动态规划很好的解决。动态规划的思想就是根据规律获得推导公式,然后解决问题。 三、 问题: Longest Common Substring 分析: 最长公共子序列问题就是和最长公共子串问题差不多,就是当当Ai != Bj 的时候,对应的c[i,j]置为0。推导公式如下: 最终c数组的最大值max对应的就是最长公共子串,只需要将从本位置向前述max-1个的子串即是所求子串。 总结: 本题就是第二题的一种特殊的情况,即c数组中的值不能从左和上两个方向获取,其他基本相同。在代码上,只需要修改小部分代码就可以实现该问题。 四、 问题: Max Sum 分析: 求和最大的子串。这个问题和第三题很像,不过这次不用二维数组而是使用两个标记来标志所求子串的起始位置(maxb)结束位置(maxe)。思路是,对于第i个元素,如果当前元素与目前选中的序列的sum小于0,那么这么序列不会被选择,更新sumb与sume的值;如果sum仍然大于0,则sum可以选中。比较sum与max的值,如果sum>max,则更新maxb与maxe 的值。递推公式如下: 遇到的问题: 在全是负数时出现问题,后来讲max的初始值设置为第一个元素的值后就能正常了。 总结: 动态规划能解决很多问题,找到递推公式非常重要。 五、 问题: Shortest path in multistage graphs. Find the shortest path from 0 to 15 for the following graph. 分析: 观察本题图的特点,发现可以将图分解为7个部分,以此可以计算到每一个节点的最短的路径。即可求出最终的最短路径。 总结: 结合本题中的特殊情况,可以采用适当的方法来处理。 第三次实验 一、 问题: Knapsack Problem. There are 5 items that have a value and weight list below, the knapsack can contain at most 100 Lbs. Solve the problem both as fractional knapsack and 0/1 knapsack. 分析: 本题是背包问题的两个解法。对于部分背包来说比较简单,就是将单位价值大的物品优先放置到背包中,这样就能在背包中获取最大的价值。但是对于0/1背包问题来说,就相对复杂了。可以通过贪心算法解决。经过分析,我们转化这个问题为将n件物品放置到容量为w的容器中。这里,每件物品只可能有一个状态:放入/不放入,我们用0/1来对应。用v[i,w]来表示前i 件物品选出重量不超过w的物品,并且构成的最大的价值。那么,可以分析得出v[i,w]的递推式。如果i=0或者w=0,显然v[I,w] = 0;如果第i件物品的重量wi>w则i不可能放入容器中;如果i能够放入容器(即wi 这样,我们可以认为,每一次都恰到好处的选择了放或者不放一个物品。 直到最后一个物品,我们得到的一定就是最好的结果 总结: 背包问题是一个典型的贪心算法的例子。在解决问题的时候可以将当前步骤做到最好,然后通过推导,有可能得到一个关系式,这样就能使问题得到解决。在本题中,我们可以通过第i件物品是否应该放在容量的w的背包中进行分析,最终得到了一个递推式。