// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<int,int> ii;

typedef vector<int> vi;

typedef vector<ii> vii;

// #define debug(x) cout << #x << " : " << x;

const double PI = acos(-1);



int x[4] = {0, -1, 0, 1};

int y[4] = {1, 0, -1, 0};



char arr[1010][1010];

int cnt[1010][1010];

int h, w;



int main(){

	// ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

	cin >> h >> w;



	memset(cnt, -1, sizeof(cnt));



	for (int i = 1; i <= h; i++) 

		for (int j = 1; j <= w; j++) 

			cin >> arr[i][j];



	queue<pair<ii, int > > q;



	for (int i = 1; i <= h; i++) {

		for (int j = 1; j <= w; j++) {

			if (arr[i][j] == '#') {

				q.push({{i, j}, 0});

			}

		}

	}



	int ans = 0;



	while (!q.empty()) {

		int u = q.front().first.first;

		int v = q.front().first.second;

		int dist = q.front().second;

		q.pop();



		for (int i = 0; i < 4; i++) {

			int tx = u + x[i];

			int ty = v + y[i];



			if (tx > 0 && tx <= h && ty > 0 && ty <= w) {

				if ((cnt[tx][ty] > dist + 1 || cnt[tx][ty] == -1) && arr[tx][ty] == '.') {

					cnt[tx][ty] = dist + 1;

					q.push({{tx, ty}, cnt[tx][ty]});

				}

			}

		}

	}



	for (int i = 1; i <= h; i++) {

		for (int j = 1; j <= w; j++) {

			// cout << cnt[i][j] << ' ' ;

			ans = max(ans, cnt[i][j]);

		}

		// cout << endl;

	}



	cout << ans << endl;

}

// Faster C++ solution for the same problem (measured speedup: 5.12127257188279x):
# include <iostream>

# include <queue>

# include <climits>

using namespace std;

 

int H;

int W;

char A[1005][1005];

int counter=0;

int shortestpath[1005][1005];

bool visited[1005][1005];

int maximum=INT_MIN;

int dr[4]={1, -1, 0, 0};

int dc[4]={0, 0, -1, 1};

queue< pair<int, int> > starting;



bool inside (int row, int column)

{

    if (row<0 || row>H || column<0 || column>W)

    {

        return false;

    }



    return true;

}



void bfs (queue< pair<int, int> > starting)

{

    queue< pair<int, int> > q;



    while (!starting.empty())

    {

        q.push(make_pair(starting.front().first, starting.front().second));

        visited[starting.front().first][starting.front().second]=true;

        starting.pop();

    }



    while (!q.empty())

    {

        pair<int, int> u=q.front();

        q.pop();



        for (int i=0; i<4; i++)

        {

            int nextrow=u.first+dr[i];

            int nextcolumn=u.second+dc[i];



            if (inside(nextrow, nextcolumn) && !visited[nextrow][nextcolumn])

            {

                shortestpath[nextrow][nextcolumn]=shortestpath[u.first][u.second]+1;

                q.push(make_pair(nextrow, nextcolumn));

                visited[nextrow][nextcolumn]=true;

            }

        }



    }

}



int main()

{

    cin>>H>>W;



    for (int i=1; i<=H; i++)

    {

        for (int j=1; j<=W; j++)

        {

            cin>>A[i][j];



            if (A[i][j]=='#')

            {

                starting.push(make_pair(i, j));

            }

        }

    }



    bfs(starting);



    for (int i=1; i<=H; i++)

    {

        for (int j=1; j<=W; j++)

        {

            if (shortestpath[i][j]>maximum)

            {

                maximum=shortestpath[i][j];

            }

        }

    }



    cout<<maximum<<endl;

}