temp[i][j] = $\sum a[k][l]$ , 1<=k<=i e 1<=l<=j
Podemos calcular temp de uma maneira inteligente fazendo as seguintes observações:
Usando o principio da inclusão-exclusão, temos o seguinte:
$temp[i,j] = temp[i-1,j] + temp[i,j-1] - temp[i-1,j-1] + a[i,j]$
Com a tabela temp calculada, podemos encontrar a soma de uma submatriz que está em cinza rapidamente da seguinte maneira:
$soma = temp[k,l] - temp[k,j-1] - temp[i-1,l] + temp[i-1,j-1]$
Considere a seguinte matriz a:
1
|
2
|
-1
|
-3
|
-1
|
4
|
1
|
-5
|
2
|
A matriz temp calculada seria:
0
|
0
|
0
|
0
|
0
|
1
|
3
|
2
|
0
|
-2
|
-1
|
2
|
0
|
-1
|
-5
|
0
|
O algoritmo trivial consiste em variar todas as possibilidade i,j,k e l.
void seg_max2d( int **a, int n,int m, int & x1,int & y1 , int & x2, int & y2, int & max){
int i,j,k,l;
int temp[n+1][m+1];
int soma;
for(i=0;i<=n;i++) temp[i][0] = 0;
for(j=0;j<=m;j++) temp[0][j] = 0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
temp[i][j] = temp[i-1][j] + temp[i][j-1] - temp[i-1][j-1] + a[i-1][j-1];
max = -1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
for(k=i;k<=n;k++)
for(l=j;l<=m;l++){
soma = temp[k][l] - temp[i-1][l] - temp[k][j-1] + temp[i-1][j-1];
if(soma > max){
max = soma;
x1 = i;
y1 = j;
x2 = k;
y2 = l;
}
}
}
No exemplo acima, a soma máxima é 6 e a submatriz é a[2..3,3..3].A complexidade desse algoritmo é O($n^4$). Podemos aplicar o algoritmo de kadane1D para reduzir a complexidade do algoritmo para O($n^3$).
A idéia do algoritmo kadane2D é aplicar o algoritmo de kadane1D nos seguintes vetores:
Considere a seguinte matriz a:
1
|
2
|
-1
|
-3
|
-1
|
4
|
1
|
-5
|
2
|
1° vetor = 1° linha
1 2 -1 = segmento de soma máxima [1 2] soma 3
2° vetor = 1° linha + 2° linha
-2 1 3 = segmento de soma máxima [1 3] soma 4
3° vetor = 1° linha + 2° linha + 3° linha
1 -4 5 = segmento de soma máxima [5] soma 5
4° vetor = 2° linha
-3 -1 4 = segmento de soma máxima [4] soma 4
5° vetor = 2° linha + 3° linha
2 -6 6 = segmento de soma máxima [6] soma 6
6° vetor = ° linha
1 -5 2 = segmento de soma máxima [2] soma 2
void kadane2d( int **a, int n,int m, int & x1,int & y1 , int & x2, int & y2, int & max_sum){
int i,j,k;
int tmp[m];
int fy1,fy2;
int cur;
for (i=0; i< n; i++)
{
for(k=0; k<m; k++)
tmp[k] = 0;
for (j=i; j<n; j++)
{
for(k=0; k<m; k++)
tmp[k] += a[j][k];
kadane(tmp, m, fy1, fy2, cur);
if (cur > max_sum)
{
y1 = fy1;
y2 = fy2;
x1 = i;
x2 = j;
max_sum = cur;
}
}
}
}


Um comentário:
Obrigado Wladimir, sua explicação me ajudou muito aqui.
Postar um comentário