算法第三章上机实践报告
1.1问题描述
一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。
这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用?
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。
输入格式:
第一行是一个整数,表示正方形的宽度N (1≤N<100);
后面N行,每行N个不大于100的整数,为网格上每个小方格的费用。
输出格式:
至少需要的费用。
1.2算法描述
题目关键条件:商人在花费(2N-1)个时间单位。由此可以推出商人不能对角方向行驶,只能向上下左右四个方向移动。进一步推敲可得,商人只能往右或者往下移动。因此,创建一个二维数组m[i][j],记录从上一个位置到该位置的最小花费,那么最后m[n][n]的值就是答案。
1.3问题求解
1.1.1根据最优子结构性质,列出递归方程式
除了第一行和第一列外的其他元素,到达该元素位置的前提是上一个到达的网格点位置在该元素位置的左边或上边,因此先判定该元素左边和上边的值哪个比较小,选择较小的值加上该位置所需消耗费用即为该位置的最低通行费用,即最优解。
递归方程式可列为: m[i][j] = a[i][j] + min(m[i-1][j] , m[i][j-1]) (i > 1,j > 1)
m[i][j] = a[i][j] + m[i-1][j] (j = 1)
m[i][j] = a[i][j] + m[i][j-1] (i = 1)
1.1.2给出填表法中表的维度、填表范围和填表顺序
填表范围:i从1到n,j从1到n。其中i=1时,m[1][j]=m[1][j-1]+a[1][j],a[i][j]为每个网格点所需消耗费用的二维数组;同理,j=1时,m[i][1]=m[i-1][1]+a[i][1]。
i,j>=2时,按1.1.1中递归方程式填表。
填表顺序:除去第一行向右累加,第一列向下累加外,从第二行第二个元素开始,按从左到右顺序求出第二行每个元素最优解,然后在往下进行第三行的元素最优值求解,一直到第n行最后一个元素解答出来。
因此顺序是从左到右,从上到下。
1.1.3分析该算法的时间和空间复杂度
时间复杂度:O(n^2) 二重循环
空间复杂度:O(n^2) 二维数组
1.3心得体会
第一步主要先找出关键核心方程式,再细心处理边界问题,答案思路遍清晰明了。
2.对动态规划算法的理解与体会
动态规划算法用历史记录来不断更新最优解。其基本思想与分治法相似,也是将求解问题分解成若干子问题并按顺序求解,因此二维数组的建立亦需要确定填表的范围与顺序才能得到正确的结果,而为减少重复计算,有些局部的计算是不必要的,所以一般二维数组的建立也只需要半个三角形的求解范围而已。而动态规划算法的核心在于递归,解决先序的子问题后再往下得到后序子问题的答案,是动态规划算法的关键点所在。