1と0でいっぱいの巨大なファイルで、1の最大の正方形を見つける必要があります。動的プログラミングを使用する必要があることはわかっています。 2D配列に格納しています。最大の正方形を見つけるためのアルゴリズムの助けがあれば素晴らしいです、ありがとう!
入力例:
1 0 1 0 1 0
1 0 1 1 1 1
0 1 1 1 1 1
0 0 1 1 1 1
1 1 1 1 1 1
回答:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
これまでの私のコード:
int Square (Sq[int x][int y]) {
if (Sq[x][y]) == 0) {
return 0;
}
else {
return 1+MIN( Sq(X-1,Y), Sq(X,Y-1), Sq(X-1,Y-1) );
}
}
(すでに配列に値が入力されていると想定)
int main() {
int Sq[5][6]; //5,6 = bottom right conner
int X = Square(Sq[5][6]);
}
そこからどうすればいいですか?
これがソリューションのスケッチです:
各セルについて、そのセルを左上として使用して正方形を作成できる大きさのカウンターを保持します。明らかに、0のすべてのセルはカウントとして0を持ちます。
右下のセルから反復を開始し、左下に移動してから、1行上に移動して繰り返します。
各スキャンでこれを行います:
count=0
を割り当てますcount=1
を割り当てます。max_count
変数を保持します。行列のトラバースの最後に、max_count
は目的の値になります。
複雑さは、マトリックスの走査のコストにすぎません。
これは、走査後のマトリックスの外観です。括弧内の値はカウント、つまりセルを左上として使用して作成できる最大の四角形です。
1(1) 0(0) 1(1) 0(0) 1(1) 0(0)
1(1) 0(0) 1(4) 1(3) 1(2) 1(1)
0(0) 1(1) 1(3) 1(3) 1(2) 1(1)
0(0) 0(0) 1(2) 1(2) 1(2) 1(1)
1(1) 1(1) 1(1) 1(1) 1(1) 1(1)
def max_size(mat, ZERO=0):
"""Find the largest square of ZERO's in the matrix `mat`."""
nrows, ncols = len(mat), (len(mat[0]) if mat else 0)
if not (nrows and ncols): return 0 # empty matrix or rows
counts = [[0]*ncols for _ in xrange(nrows)]
for i in reversed(xrange(nrows)): # for each row
assert len(mat[i]) == ncols # matrix must be rectangular
for j in reversed(xrange(ncols)): # for each element in the row
if mat[i][j] != ZERO:
counts[i][j] = (1 + min(
counts[i][j+1], # east
counts[i+1][j], # south
counts[i+1][j+1] # south-east
)) if i < (nrows - 1) and j < (ncols - 1) else 1 # edges
return max(c for rows in counts for c in rows)
LSBRA(X,Y)
は、「X、Yで右下にある最大の正方形」を意味します
疑似コード:
_LSBRA(X,Y):
if (x,y) == 0:
0
else:
1+MIN( LSBRA(X-1,Y), LSBRA(X,Y-1), LSBRA(X-1,Y-1) )
_
(エッジセルの場合、MIN部分をスキップして、(x、y)が0でない場合は1を返すことができます。)
次のように、「ウェーブ」でグリッドを斜めに通過します。
_ 0 1 2 3 4
+----------
0 | 1 2 3 4 5
1 | 2 3 4 5 6
2 | 3 4 5 6 7
3 | 4 5 6 7 8
_
または、エッジセルに入力している限り、左から右、上から下の順に作業します。
_ 0 1 2 3 4
+----------
0 | 1 2 3 4 5
1 | 6 7 8 9 .
2 | . . . . .
3 | . . . . .
_
そうすれば、必要なデータを以前に計算したことがない計算に遭遇することは決してありません。したがって、すべてのLSBRA()
"calls"は、実際には以前の計算結果の単なるテーブルルックアップです(したがって動的プログラミング)側面)。
動作する理由
X、Yで右下の正方形を作成するには、他の3つのコーナーのそれぞれに接する、寸法が1つ少ない重複する正方形が含まれている必要があります。つまり、
_XXXX
XXXX
XXXX
XXXX
_
あなたも持っている必要があります...
_XXX. .XXX .... ....
XXX. .XXX XXX. ....
XXX. .XXX XXX. ....
.... .... XXX. ...X
_
これら3つ(各LSBRAチェック)のNサイズの正方形に加えて現在の正方形も「占有」されている限り、(N + 1)サイズの正方形になります。
私の頭に浮かぶ最初のアルゴリズムは次のとおりです。
実装は非常に簡単なので、問題は宿題のように聞こえません。さらに、入力が非常に大きい場合、これが遅くなるため、これを行うにははるかに効率的な方法がある可能性があります。
入力行列をM
としましょう:n x m
T[i][j]
は、正方形の右下角が最大の正方形の辺を含むDPマトリックスです(i,j)
。
テーブルを満たすための一般的なルール:
if (M[i][j] == 1) {
int v = min(T[i][j-1], T[i-1][j]);
v = min(v, T[i-1][j-1]);
T[i][j] = v + 1;
}
else
T[i][j] = 0;
結果の正方形サイズはT
の最大値です。
充填 T[i][0]
およびT[0][j]
はささいなことです。
このアルゴを巨大なファイルに使用できるかどうかはわかりませんが、-マトリックスT
全体を保存する必要はありませんが、現在と以前の行のみ。
以下のメモは、一般的な考え方を理解するのに役立ちます。
ここで重要なのは、動的プログラミングを使用して、実際のエリアではなく、エリアのrootを追跡できることです。
アルゴリズムは次のとおりです。
Max-squareと呼ばれるintの2D配列を格納します。ここで、インデックスi、jの要素は、それが入っている正方形のサイズを表し、i、jは右下隅です。 (max [i、j] = 2の場合、インデックスi、jがサイズ2 ^ 2 = 4の正方形の右下隅であることを意味します)
各インデックスi、jについて:
ifi、jで要素が0の場合、max-square i、jを0に設定します。
else:
Max-square [i-1、j]とmax-square [i、j-1]とmax-square [i-のminimumを見つけます1] [j -1]。 max-square [i、j]を1 + 3の最小値に設定します。帰納的に、max-square配列を埋めることになります。プロセス内の最大値を検索または追跡し、その値を返します^ 2。
人々が提案したこれらのソリューションを見てください: https://leetcode.com/discuss/questions/oj/maximal-square?sort=votes
わかりました。最も非効率的な方法ですが、簡単な方法は次のとおりです。
最初のアイテムを選択します。 1かどうかを確認します。1の場合、1x1の正方形があります。
下の1つと右の1つをチェックし、1の場合は、行2の列2をチェックします。1の場合は、2x2の正方形です。
行3の列1、列2、列3に加えて、行1の列3、行2の列3、1の場合は3x3をチェックします。
したがって、基本的には行と列を一緒に展開し続け、境界内のすべてのセルをチェックします。 0を押すとすぐに壊れるので、1ポイント続けて移動し、最初からやり直します。
行の終わりで、次の行に移動します。
終わりまで。
おそらく、それらがwhileループなどにどのように適合するか、&&
sを使用して0を確認する方法を確認できます。また、これを見ると、どのように高速化できるかに気付くでしょう。しかし、他の答えが述べたように、それは宿題のように聞こえるので、実際のコードはあなたに任せます。
幸運を!
Nを2D配列のセルの量とします。すべての最大の空の長方形をリストする非常に効率的なアルゴリズムが存在します。最大の空の四角形はこれらの空の四角形の1つ内にあり、最大の空の四角形のリストが計算されると、それを見つけるのは簡単です。このようなリストを作成するためのO(N)アルゴリズムを提示する論文は www.ulg.ac.be/telecom/rectangles とソースコードで見つけることができます(最適化されていません。)最大の空の四角形の数がNで囲まれているという証明が存在することに注意してください(論文を参照)。したがって、最大の空の四角形の選択はO(N)で行うことができ、全体的な方法もOです。 (N)実際には、この方法は非常に高速です。コード全体がCの40行を超えてはならないため、実装は非常に簡単です(すべての最大の空の四角形をリストするアルゴリズムは、Cの約30行かかります) )。