Advertisement
Fhernd

matrix-land-description.txt

Nov 11th, 2018
234
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.61 KB | None | 0 0
  1. Let's say we have a 4*16 matrix looks like this:
  2.  
  3. [ 4 5 3 0 -3 0 3 1 -4 3 8 -4 -1 9 1 8]
  4. [ 2 -1 -6 8 8 -7 -5 1 0 -4 -5 -5 2 -7 -8 6]
  5. [-7 -8 -7 -6 -5 -1 -3 3 6 -7 4 -7 -5 0 -5 1]
  6. [-9 6 -4 -1 7 -7 -7 5 8 8 3 -6 3 -2 0 -1]
  7. We want to calculate the highest value path to each square like this:
  8.  
  9. [33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33]
  10. [44 44 44 49 49 42 38 38 38 34 29 30 35 28 31 39]
  11. [37 36 37 43 49 49 49 49 49 46 46 39 34 35 35 40]
  12. [58 67 67 67 67 67 67 73 73 73 73 70 70 68 68 67]
  13. The answer of course will be the highest value on the bottom row, 73 in this case.
  14.  
  15. This is done line by line. For each square, there are three parameters that define the highest value path:
  16.  
  17. How far left the path goes on that line.
  18. How far right the path goes on that line.
  19. The square on the line above you drop down from.
  20. We can brute force this, but it is O(n*m^4).
  21.  
  22. We can reduce that to O(n*m^3) if we note that how far the path goes to the left is largely independent of how far it goes to the right, except for which side we drop down from the line above. We can therefore find the best way to drop down from either side, then how far we should go in either direction if we don't drop down that side.
  23.  
  24. We can further reduce it to O(n*m^2) because finding the best square to drop down from is a simple maximum that we can calculate while figuring out how far we should go. But we really need O(n*m).
  25.  
  26. Kadane's algorithm is the key to this. Kadane's algorithm finds the maximum subarray in an array. It looks like this:
  27.  
  28. max_subarray = arr[0]
  29. subtotal = 0
  30. for value in arr:
  31. subtotal = max(value, subtotal + value)
  32. max_subarray = max(subtotal, max_subarray)
  33. The subtotal gives the maximum subarray that stops at a particular square. If we proceed rightwards through a line on the grid, we can determine how far left the path should go from each square. If we proceed leftwards we can also determine how far right to go from each square. And this is O(m).
  34.  
  35. Accounting for the fact that we must drop down from a square above can be done with the same principle.
  36.  
  37. import sys
  38. from array import array
  39.  
  40. def matrixLand(grid):
  41. width = len(grid[0])
  42. prevline = array('l',[0]) * width
  43.  
  44. for line in grid:
  45. going_left = array('l',[0]) * width
  46. going_right = array('l',[0]) * width
  47.  
  48. top, notop = -2000000000, 0
  49. for i in range(width):
  50. notop = max(0,notop)
  51. going_right[i] += notop
  52. notop += line[i]
  53. top = max(top+line[i], prevline[i]+notop)
  54. going_left[i] += top
  55.  
  56. top, notop = -2000000000, 0
  57. for i in range(width-1,-1,-1):
  58. notop = max(0,notop)
  59. going_left[i] += notop
  60. notop += line[i]
  61. top = max(top+line[i], prevline[i]+notop)
  62. going_right[i] += top
  63.  
  64. for i in range(width):
  65. prevline[i] = max(going_left[i], going_right[i])
  66.  
  67. return max(prevline)
  68.  
  69.  
  70. n, m = [int(x) for x in input().split()]
  71.  
  72. if m == 1:
  73. print(sum(int(x) for x in sys.stdin))
  74. else:
  75. grid = []
  76. for _ in range(n):
  77. grid.append(array('l',(int(x) for x in sys.stdin.readline().split(' '))))
  78. result = matrixLand(grid)
  79. print(result)
  80. You may notice that I have written special case code for the m = 1 case. TC#19 is n = 4 million, m = 1, and the per line overhead is just too much for PyPy. Even the special case code, using sys.stdin instead of input(), takes 3 seconds. TC#20 is n = 1, m = 4 million and forces us to use arrays instead of lists to avoid running out of memory.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement