1 <?php 2 #求二维矩阵的最大子矩阵 3 4 #构造求和表 5 #s[i][j]表示从1..i行,1..j列所有元素之和 6 #可以利用公式s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1]s[j - 1] + a[i][j]求得 7 function build_sum_tab($a) { 8 #初始化第0列和 9 for ($i = 0; $i < count($a); $i++) { 10 $s[$i][0] = 0; 11 for ($j = 0; $j <= $i; $j++) { 12 $s[$i][0] += $a[$j][0]; 13 } 14 } 15 16 #初始化第0行和 17 for ($i = 0; $i < count($a[0]); $i++) { 18 $s[0][$i] = 0; 19 for ($j = 0; $j <= $i; $j++) { 20 $s[0][$i] += $a[0][$j]; 21 } 22 } 23 24 for ($i = 1; $i < count($a); $i++) { 25 for ($j = 1; $j < count($a[0]); $j++) { 26 $s[$i][$j] = $s[$i - 1][$j] + $s[$i][$j - 1] - $s[$i - 1][$j - 1] + $a[$i][$j]; 27 } 28 } 29 30 return $s; 31 } 32 33 #计算最大子矩阵 34 function max_sub_matrix($a, $s) { 35 $rows = count($a); 36 $cols = count($a[0]); 37 #限定行的上下界 38 $max_sum = 0; 39 for ($low = 0; $low < $rows; $low++) { 40 for ($high = $rows - 1; $high >= $low; $high--) { 41 #将确定上下界的行进行线性查找 42 #利用求和数组算出单列的和值,将这个上下界行矩阵看成一维矩阵求连续最大子序列和 43 #单列和值利用公式 sc = s[high][col] - s[low - 1][col] - s[high][col - 1] + s[low - 1][col - 1] 求得 44 $sum = $s[$high][0] - (isset($s[$low - 1][0]) ? $s[$low - 1][0] : 0); 45 $max_sum = max($max_sum, $sum); 46 for ($col = 1; $col < $cols; $col++) { 47 $sum_col = $s[$high][$col] - $s[$high][$col - 1] - (isset($s[$low - 1][$col]) ? $s[$low - 1][$col] : 0) + (isset($s[$low - 1][$col]) ? $s[$low - 1][$col - 1] : 0); 48 // echo "low: {$low} high: {$high} sum: {$sum} max: {$max_sum} sum_col: {$sum_col}<br>"; 49 $sum = max($sum_col, $sum + $sum_col); 50 $max_sum = max($max_sum, $sum); 51 } 52 } 53 } 54 55 return $max_sum; 56 } 57 58 #随机二维数组生成器 59 function build_matrix($n, $m) { 60 $a = array(); 61 for ($i = 0; $i < $n; $i++) { 62 for ($j = 0; $j < $m; $j++) { 63 $a[$i][$j] = rand(-9, 9); 64 } 65 } 66 67 return $a; 68 } 69 70 $a = build_matrix(2, 2); 71 $s = build_sum_tab($a); 72 $max = max_sub_matrix($a, $s); 73 print_r($a); 74 echo "<br>"; 75 print_r($s); 76 echo "<br>"; 77 print_r($max); 78 ?>