PHP 求n*m二维矩阵最大子矩阵 O(n*n*m)

 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  ?>

转载于:https://www.cnblogs.com/zemliu/archive/2012/05/05/2484420.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值