初阶:有一个n*m的矩阵,需要从坐上角(1,1)走到右下角(n,m),只能向右和向下走。矩阵中的每个方格有一个非负整数,问从左上角到右下角的所有路径中,数字之和最大的路径是哪一条。
进阶:如果可以从左上角往下走k次,每个方格中的数被取走之后第二次经过则不再累加数值。请问走k次最多能取到的数值之和是多少。
解答
答:
初阶:采用动态规划算法。F[i][j]代表从左上角到(i,j)这个位置的最大路径和。有F[i][j] = max{F[i-1][j], F[i][j-1]} + A[i][j]。其中A[i][j]为(i,j)这个格子中的数值。答案为F[n][m]。时间复杂度O(n*m)。
进阶:采用网络流算法。将每个格子拆为两个点――入点和出点,入点到出点之间的流量限制为1,费用为格子的数值。所有出点均向它右方和下方的入点连一条流量限制为无穷大,费用为0的边。连接源点到左上角入点,流量设为k,费用设为0。设右下角的出点为汇点。从源点到汇点做一次最小费用最大流算法,即可得到答案。
面试官角度:
初阶问题是经常会被问到的问题。也是必须要掌握的动态规划算法问题之一。类似的题目有数字三角形。进阶问题一般不会被问到,在北美的面试中基本没有被问到过。再国内的面试中,有一些公司很牛但招聘名额很少时会问到这个题目,笔者曾经在参加面试时被问到的这个题。一般来说网络流算法不会在面试中被问到,所以读者不用担心也不必准备此类问题。只需要掌握初阶问题这种最基本的动态规划算法即可。
Read full article from 九章算法面试题26 方格取数
No comments:
Post a Comment