AOJ 0098 Maximum Sum Sequence II
問題概要
n次正方行列(a_ij)が与えられる.(a_ij) の部分行列の要素の和の最大値を求めよ.
・制約
1 <= n <= 100
解法
まず,要素の横方向について累積和を取る.
その後,横方向のある区間[i, j]を固定して考えてみる.
この区間の第 k 行の和はsum[k][j] - sum[k][i] である.
Sij[k] := sum[k][j] - sum[k][i] (k = 0, ... , N-1)とおく.
すると,この区間の幅を考えたときの最大値は,Sij[k] の連続する部分列の和の最大値を求める問題に帰着できる.
これは動的計画法でとけるので,最終的な計算量は O(N^3)である.
ソースコード
#include <iostream> #include <vector> using namespace std; using ll = long long; int main() { int n; cin >> n; vector<vector<int>> a(n, vector<int>(n)); for(int i=0; i<n; ++i) { for(int j=0; j<n; ++j) { cin >> a[i][j]; } } vector<vector<int>> sum(n, vector<int>(n+1)); for(int i=0; i<n; ++i) { for(int j=0; j<n; ++j) { sum[i][j+1] += sum[i][j] + a[i][j]; } } int res = -1e9; for(int i=0; i<=n; ++i) { for(int j=i+1; j<=n; ++j) { int t = 0; for(int k=0; k<n; ++k) { if(t < 0) { t = sum[k][j] - sum[k][i]; } else { t += sum[k][j] - sum[k][i]; } res = max(res, t); } } } cout << res << endl; }