7-3 最低交通费
1.1 问题描述
一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。
这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用?
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。
输入格式:
第一行是一个整数,表示正方形的宽度N (1≤N<100);
后面N行,每行N个不大于100的整数,为网格上每个小方格的费用。
输出格式:
至少需要的费用。
输入样例:
5
1 4 6 8 10
2 5 7 15 17
6 8 9 18 20
10 11 12 19 21
20 23 25 29 33
输出样例:
109
样例中,最小值为109=1+2+5+7+9+12+19+21+33。
1.2 算法描述
本题要求解商人在规定时间内走出去所用的最少花费,这个“最少花费”就代表该大问题是由很多个小问题环环相扣组成的,我们将该大问题拆开,就可以得到很多的小问题,“最少花费”就是指我们要在小问题中找到最优解。这满足了“最优子结构”的特性,且该问题分解的小问题环环相扣,这就意味着这个题目需要我们使用动态规划的方法来写。
我觉得用“填表法”来写比较合适,因为前文说迷宫的规格是N*N,所以要创建一个N*N的表格,表格的每一个代表商人走到迷宫的同样位置所需要的最少的金钱,因为必须在2N-1的时间内走出去,所以商人只能往右走或者往下走,这样一理解,表格的最左列和最上列就可以填了,因为商人只能往下走和往右走。有了这两列的基础我们就可以将整个表格填上。
设i代表的是表格的行,j代表的是表格的列。
设表格为b[n][n],从b[1][1]开始计数。
b[1][1]=1
for(int i=2;i<=n;i++)
b[i][1]+= b[i-1][1];(将第一列填上)
for(int j=2;j<=n;j++)
b[1][j]+=b[1][j-1];(将第一行填上)
for(int i=2;i<=n;i++)
for(int j=2;j<=n;j++)
b[i][j]+=min(b[i-1][j],b[i][j-1]);(按行依次填表,最后的b[n][n]即为最小值)
1.3 问题求解:
1.1.1 根据最优子结构性质,列出递归方程式,
mf[1][1] = a[1][1]//边界条件 mf[1][j] = mf[1][j-1] + a[1][j], j>1 mf[i][1] = mf[i-1][1] + a[i][1], i>1 mf[i][j] = max{mf[i-1][j],mf[i][j-1]}+a[i][j], i>1, j>1
1.1.2 给出填表法中表的维度、填表范围和填表顺序。
表的维度为二维,填表范围为从表b[1][1]一直到b[n][n],顺序是先从第一列和第一行在按行填完整张表。
1.1.3 分析该算法的时间和空间复杂度
时间复杂度为O(n^2)
空间复杂度为O(n^2)
1.3 心得体会(对本次实践收获及疑惑进行总结)
在解决问题之前,要先看懂题目,看透题目,看题目中有无给我们隐藏的信息(比如本题的向右走和向下走),然后在思考问题。在思考问题的过程中如果碰到环环相扣的问题时,大概率就是用动态规划的方法进行解决。再写动态规划时要注意递归方程的书写,不要忘记加边界条件等等。。