/*
        题意: n*m的网格,一些网格有Light,Light有level ,能照射上下左右最多level个(包括自身)
                    现要设定一个最小的level,使得小于该level的Light都关掉,大于的都调整到该level,使得任意一个格子
                    要么自身有Light,要么竖直、水平方向都必须被灯照到

        这题一开始想到的是计算每个格子能满足条件的最小level,然后在这些level中取最大
        这样子有问题,因为这样子认定了若level0能被照到,则>level0的也能被照到,如
        5  0  0
        0  2  0
        0  0  5

        考虑每个格子的话,他能被覆盖的level,是一段一段的值,如[1,3] , [5,7] 
         这样子是比较复杂的,答案会是每个格子可选的范围的交集

        Email了两个人,非常感谢了: 【bupt】xiaofan  ,   Navi
 做法是:
        对每个Light记录它4个方向邻接的Light
        一开始假设所有Light都亮,计算每相邻Light要覆盖他们之间的格子的值,即两个距离/2,取所有这些值的最大
        以这个为起点(答案至少是这个) , 然后对小于这个level的Light都去掉,O(1)更新被影响到的邻接Light
        然后这样子不断增大的去枚举 , 发现不能覆盖完就No Answer
        否则某个level值可以覆盖所有格子,而且不用再熄Light就是答案了

        这里为了去掉小于Level的Light,先排序
 
*/

#include
<cstdio>
#include
<cstring>
#include
<algorithm>
#include
<vector>
#include
<queue>
#include
<map>
#include
<cmath>
#include
<cstdlib>
#include
<iostream>

using namespace std;

const int INF = 1000000000;
const int MAXN = 10010;


struct Light
{
    
int x, y , level;
    
int next[4]; // left  up  right  down
    Light(){}
    Light(
int _x, int _y , int _level)
    
{
        x 
= _x;
        y 
= _y;
        level 
= _level;
        
for(int i = 0; i < 4 ; i++)
            next[i] 
= -1;
    }

    
bool operator < ( const Light &B )const
    
{
        
return level < B.level;
    }

    
void update();
}
;

int n , m , ans;
int a[110][10086];
Light light[
110*10086];

void Light:: update()//去掉该Light后    O(1)更新  邻接的Light ,  覆盖相邻Light之间格子的距离
{
    
int left = next[0] ;
    
int right = next[2];
    
if(left != -1) light[left].next[2= right;
    
if(right != -1)light[right].next[0= left;

    
if(left == -1 && right == -1 )ans = INF;////////
    else if(left == -1 )ans = max(ans , light[right].y);
    
else if(right == -1)ans = max(ans , m-light[left].y+1);
    
else ans = max(ans , (light[right].y - light[left].y +2 )/2);

    
int up = next[1];
    
int down = next[3];
    
if(up != -1)light[up].next[3= down;
    
if(down != -1)light[down].next[1= up;
    
    
if(up==-1 && down ==-1)ans = INF;
    
else if(up==-1)ans = max(ans,light[down].x);
    
else if(down == -1)ans = max(ans , n-light[up].x+1);
    
else ans = max(ans , (light[down].x - light[up].x+2)/2);
}


int main()
{

#ifdef ONLINE_JUDGE
#else
    freopen(
"in""r", stdin);
#endif

    
while( scanf("%d%d",&n,&m) , n || m)
    
{
        
int tot = 0;
        
for(int i = 1; i <= n; i ++)
            
for(int j = 1 ; j <= m ; j++)
            
{
                scanf(
"%d",&a[i][j]);
                
if(a[i][j])
                
{
                    light[
++tot] = Light(i,j,a[i][j]);
                }

            }


        sort( light 
+ 1 , light + 1 + tot);
        
for(int i = 1 ; i <= tot ; i++)
            a[light[i].x][light[i].y] 
= i;            //记录为id

        ans 
= 0;

        
//left right
        for(int i = 1 ; i <= n && ans != INF ; i++)
        
{
            
int pre = -1;
            
for(int j = 1;  j <= m; j++)
            
{
               
if(a[i][j])//a[i][j] 存的是在 light[]中的位置
               {
                   
if(pre==-1)ans = max(ans , j);
                   
else
                   
{
                       ans 
= max(ans , (j-pre+2)/2);
                       light[a[i][j]].next[
0= a[i][pre];
                       light[a[i][pre]].next[
2= a[i][j];
                   }

                   pre 
= j;                   
               }

            }

            
if(pre == -1)ans = INF;
            
else ans = max(ans,m-pre+1);
        }


        
//up down
        for(int j = 1 ; j <= m && ans != INF ; j++)
        
{
            
int pre = -1;
            
for(int i = 1;  i <= n; i++)
            
{
               
if(a[i][j])
               
{
                   
if(pre==-1)ans = max(ans , i);
                   
else
                   
{
                       ans 
= max(ans , (i-pre+2)/2);
                       light[a[i][j]].next[
1= a[pre][j];
                       light[a[pre][j]].next[
3= a[i][j];
                   }

                   pre 
= i;
               }
              
            }

            
if(pre == -1)ans = INF;
            
else ans = max(ans,n-pre+1);

        }

        
int p = 1 ;
        
while( ans < INF && p <= tot && light[p].level < ans )
            light[p
++].update();
        
if(ans == INF)puts("NO ANSWER!");
        
else printf("%d\n",ans);
    }


    
return 0;
}