ブルートフォースは、適切に実装されていれば、ここでは n < 100 で問題なく動作するはずです。以下のソリューションは、O(n^4) 時間と O(n^2) メモリの複雑さを持ちます。10^8 演算は、最新の PC では 1 秒をはるかに下回るはずです (特に、各演算が非常に安価であることを考慮すると、加算と減算はほとんどありません)。
いくつかの観察
- 考慮すべき O(n^4) 個のサブ長方形があり、それぞれが解決策になる可能性があります。
- O(1)(一定時間)で各サブ長方形の1と0の数を見つけることができれば、O(n ^ 4)時間で問題を解決できます。
- 一部のサブ長方形の 1 の数がわかっている場合は、(領域を介して) ゼロの数を見つけることができます。
したがって、問題は次のようになります。データ構造を作成して、一定時間内に各サブ長方形の 1 の数を見つけることができるようにします。
さて、 sub-rectangle があると想像してください[i0..i1]x[j0..j1]
。つまり、i0 と i1 の間の行と j0 と j1 の間の列を占めます。count_ones
サブ長方形内の 1 の数をカウントする関数とします。
これが主な観察事項です。
count_ones([i0..i1]x[j0..j1]) = count_ones([0..i1]x[0..j1]) - count_ones([0..i0 - 1]x[0..j1]) - count_ones([0..i1]x[0..j0 - 1]) + count_ones([0..i0 - 1]x[0..j0 - 1])
実際の例と同じ観察:
AAAABBB
AAAABBB
CCCCDDD
CCCCDDD
CCCCDDD
CCCCDDD
D サブ長方形 (3x4) 内の 1 の数を見つける必要がある場合は、長方形全体 (A + B + C + D) 内の 1 の数を取り、(A + B) 内の 1 の数を引くことで実行できます。 (A + C) の四角形の 1 の数を減算し、(A) の四角形の 1 の数を追加します。(A + B + C + D) - (A + B) - (A + C) + (A) = D
したがって、 sub-rectangle 内の 1 の数を含むtableが必要sums
です。
このテーブルは O(n^2) で作成できますが、それを埋める直接的な方法 (面積のすべての要素をそれぞれ繰り返し)は O(n^4) になります。i
j
[0..i][0..j]
i
j
[0..i][0..j]
このテーブルを持って、
count_ones([i0..i1]x[j0..j1]) = sums[i1][j1] - sums[i0 - 1][j1] - sums[i1][j0 - 1] + sums[i0 - 1][j0 - 1]
したがって、時間計算量 O(n^4) に達しました。