题意
给出一个N*N的数字方阵,从左上角走到右下角,每次只能向右或者向下走,走过的方格数字变为0。走两次,求两条路径的最大和。
题目分析
典型的动态规划题目。
如果走一次,定义 d p [ i ] [ j ] dp[i][j] dp[i][j]为走到 i i i行 j j j列的路径最大和,由于只能向右或者向下走,则转移方程为: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + a [ i ] [ j ] dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + a[i][j] dp[i][j]=max(dp[i−1][j],dp[i][j−1])+a[i][j]。则 d p [ n ] [ n ] dp[n][n] dp[n][n]即为走到右下角的最大值。
那么,走两次的处理方式为:先跑一遍DP,将路径上的数置0,再跑一遍DP,将两次求得的 d p [ n ] [ n ] dp[n][n] dp[n][n]相加即可。这样正确么?
【举例】
对于如下方阵 a [ 3 ] [ 3 ] a[3][3] a[3][3],第一遍DP之后, d p [ N ] [ N ] dp[N][N] dp[N][N]的值为10,选择的路径如图三。
将路径1上的数值置0后,得到新的数字方阵,第二遍DP后,得到 d p [ N ] [ N ] dp[N][N] dp[N][N]的值为2,选择的路径如图三。
分开跑两次DP之后,得到两条最大的路径和为12,但是,经肉眼观察,可以找到两条更优的路径,其最大值为13。
至此,我们得到结论:先后跑两遍DP并不能得到答案。
观察上图,感性认识原因:
在第一DP时,即绿色路径,按照转移方程,选择了数字4,而不是数字2,单从第一遍DP来看,没有任何问题。但是在第二遍DP时,由于数字4已经被拿走,导致其选择的路径是向右拿数字2,而不是向下取数字1,单从第二遍DP来看,也没有问题。
但两遍DP并没有协同合作,我们希望第一遍DP取的是数字2,虽然当下不是最优,但是第二遍DP会取到数字4,达到整体最优。
因此,单独跑两遍DP,会使两者之前不能协同合作,当下的最优选择比较短视,只看到了自己,没有看到队友。
因此,必须考虑两遍DP同时进行(多线程DP),可以理解为有两个人同时从A出发到达B。
定义状态 d p [ x 1 ] [ y 1 ] [ x 2 ] [ y 2 ] dp[x1][y1][x2][y2] dp[x1][y1][x2][y2]为第一个人走到 x 1 x1 x1行 y 1 y1 y1列,第二个人走到 x 2 x2 x2行 y 2 y2 y2列的最大路径和,则情况有四种:
- 第一个人向右,第二个人向右,即为 d p [ x 1 ] [ y 1 − 1 ] [ x 2 ] [ y 2 − 1 ] dp[x1][y1-1][x2][y2-1] dp[x1][y1−1][x2][y2−1]
- 第一个人向下,第二个人向下,即为 d p [ x 1 − 1 ] [ y 1 ] [ x 2 − 1 ] [ y 2 ] dp[x1-1][y1][x2-1][y2] dp[x1−1][y1][x2−1][y2]
- 第一个人向下,第二个人向右,即为 d p [ x 1 − 1 ] [ y 1 ] [ x 2 ] [ y 2 − 1 ] dp[x1-1][y1][x2][y2-1] dp[x1−1][y1][x2][y2−1]
- 第一个人向右,第二个人向下,即为 d p [ x 1 ] [ y 1 − 1 ] [ x 2 − 1 ] [ y 2 ] dp[x1][y1-1][x2-1][y2] dp[x1][y1−1][x2−1][y2]
v = m a x ( d p [ x 1 ] [ y 1 − 1 ] [ x 2 ] [ y 2 − 1 ] , d p [ x 1 − 1 ] [ y 1 ] [ x 2 − 1 ] [ y 2 ] , d p [ x 1 − 1 ] [ y 1 ] [ x 2 ] [ y 2 − 1 ] , d p [ x 1 ] [ y 1 − 1 ] [ x 2 − 1 ] [ y 2 ] ) v = max(dp[x1][y1-1][x2][y2-1], dp[x1-1][y1][x2-1][y2], dp[x1-1][y1][x2][y2-1],dp[x1][y1-1][x2-1][y2]) v=max(dp[x1][y1−1][x2][y2−1]