赞
踩
动态规划中有的题往往需要对dp数组斜着遍历,例如dp[ i ][ j ]的值主要由dp[ i ][ j-1 ]和dp[ i+1 ][ j ]两个值的大小决定,即向右上斜着遍历。
n = len(dp)
for l in range(1, n):
for i in range(n - l):
j = l + i
dp[i][j] .....
这样既可完成遍历
可以看一个5 * 5的矩阵
在上图中,如果不考虑中间的对角线,只看右上角的斜线的话,对于5*5的二维数组,有4条斜线,表示我们要遍历4次。所以在第一层循环中的代码为
for l in range(1, 5)
那么 l 的值分别为1,2, 3,4
再来看每次遍历时,行(i)的变化
在第一次遍历时(l = 1),i 的位置依次为 0 1 2 3,遍历4行(5-1);
在第二次遍历时(l = 2),i的位置依次为 0 1 2,遍历3行(5-2);
在第三次遍历时(l = 3),i的位置依次为 0 1,遍历2行(5-3);
在第四次遍历时(l = 4),i的位置依次为 0,遍历1行(5-4);
所以 i 的可选范围是在range(5 - l)之中的,即:
for i in range(5 - l)
然后来看看列(j)的位置变化
同上可知
j = 1 2 3 4
j = 2 3 4
j = 3 4
j = 4
把l, i, j按如下排列一下:
l = 1---------------2------3----- 4
i = 0 1 2 3; 0 1 2; 0 1; 0
j = 1 2 3 4; 2 3 4; 3 4; 4
是不是可以看出 j = l + i
把5给替换成n
如此就推算出了斜着遍历的代码。
如果需要考虑dp[i][i]该怎么写:
还是以一个5*5的二维数组来看,考虑对角线的话,遍历次数就从5-1次变成了5次
for l in range(5)
按照上面的推算方式
l = -----0----------1--------2-----3----4
i = 0 1 2 3 4; 0 1 2 3; 0 1 2; 0 1; 0
j = 0 1 2 3 4; 1 2 3 4; 2 3 4; 3 4; 4
把5换成n,可以得出
for l in range(n):
for i in range(n - l):
j =l + i
dp[i][j] .....
那如果想遍历二维数组的左下角怎么办:
这里同样是从 5 * 5长度推算到 n * n的长度,过程不表
for l in range(n):
for i in range(l, n):
j = i - l
dp[i][j].....
遍历二维数组的左上角:
for l in range(n-1, -1, -1):
for i in range(l, -1, -1):
j = l - i
dp[i][j].....
遍历二维数组的右下角:
for l in range(n):
for i in range(n-1, l-1, -1):
j = n + l - i - 1
dp[i][j].....
注意,这里无论是左上角还是右下角,所有的遍历方向都是从二维数组的左/右对角线开始的。如果想从顶点开始斜着遍历数组,把上面的代码稍微改一下即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。