给定一个MN的矩阵,其中一些格子是空地(F),其他是障碍(R),找出一个全部由F组成的面积最大的子矩阵。JAVA代码给出O(N^2)算法。
参考文献:《算法竞赛入门经典训练指南》P51,刘汝佳,陈锋
package ProgrammingContest;
public class CityGame_SEERC_2004 {
public static int min(int x, int y) {
return ( x < y ) ? x : y;
}
public static int solve(short[][] map) {
int M = map.length, N = map[0].length;
int[][] up = new int[M][N];
int[][] left = new int[M][N];
int[][] right = new int[M][N];
// left for 1st & last colum
for ( int i=0; i<M; i++ ) {
left[i][0] = ( map[i][0] == 0 ) ? 0 : -1;
right[i][N-1] = ( map[i][N-1] == 0 ) ? 0 : -1;
}
// up for 1st line
for ( int j=0; j<N; j++ ) up[0][j] = ( map[0][j] == 0 ) ? 0 : -1;
// left for 1st line
for ( int j=1; j<N; j++ ) left[0][j] = ( map[0][j] == 0 ) ? left[0][j-1]+1 : -1;
// right for 1st line
for ( int j=N-2; j>=0; j--) right[0][j] = ( map[0][j] == 0 ) ? right[0][j+1]+1 : -1;
//calculate up for each cell
for ( int i=1; i<M; i++ ) {
for ( int j=0; j<N; j++ ) {
up[i][j] = (map[i][j]==0)?up[i-1][j]+1:-1;
}
}
for ( int i=1; i<M; i ++ ) {
//calculate left for each cell
for ( int j=1; j<N; j++ ) {
if ( map[i][j] == 0 ) {
left[i][j] = min(left[i][j-1]+1, left[i-1][j]);
} else {
left[i][j] = -1;
}
}
//calculate right for each cell
for ( int j=N-2; j>=0; j-- ) {
if ( map[i][j] == 0 ) {
right[i][j] = min(right[i][j+1]+1,right[i-1][j]);
} else {
right[i][j] = -1;
}
}
}
int res = 0;
for ( int i=0; i<M; i++ ) {
for ( int j=0; j<N; j++ ) {
if ( map[i][j] == 0 ) {
int s = (up[i][j]+1)*(left[i][j]+right[i][j]+1);
if ( s > res ) res = s;
}
}
}
return res;
}
/**
* @param args
*/
public static void main(String[] args) {
short[][] map = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 1, 0, 0 }
};
int res = solve(map);
System.out.println(res);
}
}