首先计算从0, 0 到W-1, H-1 的所有i, j 的矩阵和。这可以使用动态编程在O(W*H) 中完成。其中的递归关系类似于F(i, j) = F(i, j-1) + F(i-1, j) - F(i-1, j-1) + M[i][j]。然后我们可以创建一个 2D Fenwick 树并将这些值插入其中。那么对于这棵树中的i, j,我们可以得到O(log(W)*log(H))中的累积和。因此对于所有i, j,总时间将是O(W*H*log(W)*log(H))。
这两个基本步骤的代码:
#include <iostream>
#include <vector>
using namespace std;
int sum(const vector<vector<int>>& BIT2D, int x, int y)
{
int res = 0;
for (int i = x; i > 0; i -= i & -i)
for (int j = y; j > 0; j -= j & -j)
res += BIT2D[i][j];
return res;
}
void add(vector<vector<int>>& BIT2D, int x, int y, int value)
{
for (int i = x; i < BIT2D.size(); i += i & -i)
for (int j = y; j < BIT2D[i].size(); j += j & -j)
BIT2D[i][j] += value;
}
int foobar(const vector<vector<int>>& matrix, vector<vector<int>>& dp, int i, int j)
{
if (dp[i][j] != -1)
return dp[i][j];
if (i == 0 || j == 0)
return dp[i][j] = 0;
return dp[i][j] = foobar(matrix, dp, i, j - 1) + foobar(matrix, dp, i - 1, j) - foobar(matrix, dp, i - 1, j - 1) + matrix[i - 1][j - 1];
}
int main()
{
int N, M;
cin >> N >> M;
vector<vector<int>> matrix(N, vector<int>(M)), dp(N + 1, vector<int>(M + 1, -1));
for (int i = 0; i < matrix.size(); ++i)
for (int j = 0; j < matrix[i].size(); ++j)
cin >> matrix[i][j];
foobar(matrix, dp, N, M);
vector<vector<int>> BIT2D(N + 1, vector<int>(M + 1));
for (int i = 1; i < dp.size(); ++i)
for (int j = 1; j < dp[i].size(); ++j)
add(BIT2D, i, j, dp[i][j]);
for (int i = 1; i < BIT2D.size(); ++i)
{
for (int j = 1; j < BIT2D[i].size(); ++j)
cout << sum(BIT2D, i, j) << ' ';
cout << endl;
}
}
对第二个矩阵做同样的事情,然后我们可以计算SAD。事实上,如果修改正确,您可以在一次调用foobar 内对第二个矩阵进行相同的计算(以及计算SAD)。时间复杂度将保持O(W*H*log(W)*log(H))。
编辑:可以在O(W*H) 中计算累积和。无需创建 Fenwick 树。在传递给foobar 的第一个调用的dp 上再次调用foobar,并将结果存储在dp2。