0

Given a binary matrix of size N x M. The task is to find the distance of nearest 1 in the matrix for each cell. The distance is calculated as |i1 – i2| + |j1 – j2|, where i1, j1 are the row number and column number of the current cell and i2, j2 are the row number and column number of the nearest cell having value 1.

Input: The first line of input is an integer T denoting the number of test cases. Then T test cases follow. Each test case consists of 2 lines . The first line of each test case contains two integers M and N denoting the number of rows and columns of matrix . Then in the next line are N*M space separated values of the matrix (mat) .

Output: For each test case in a new line print the required distance matrix in a single line separated by space.

 Constraints:
    1 <= T <= 20
    1 <= N, M <= 500

    Example:
        Input:
        2
        2 2 
        1 0 0 1
        1 2
        1 1

    Output:
    0 1 1 0
    0 0

Explanation:

Testcase 1:
1 0
0 1
0 at {0, 1} and 0 at {1, 0} are at 1 distance from 1s at {0, 0} and {1, 1} respectively.

Code:

bool isSafe(int currRow,int currCol,int n,int m){
    return currRow>=0 && currRow<n && currCol>=0 && currCol<m;
}

int bfs(int currX,int currY,vector<int> matrix[],int n,int m) {
    queue<pair<int,int>> q;
    q.push(make_pair(currX,currY));
    static int rows[]={0,-1,0,1};
    static int columns[]={1,0,-1,0};
    int flag=0;
    int dist=0;
    while(flag==0 && !q.empty()) {
        pair<int,int> p=q.front();
        q.pop();
        for(int i=0;i<4;i++) {
            if(isSafe(p.first+rows[i],p.second+columns[i],n,m)) {
                if(matrix[p.first+rows[i]][p.second+columns[i]]) {
                    dist=abs(p.first+rows[i]-currX)+abs(p.second+columns[i]-currY);
                    flag=1;
                    break;
                } else {
                    q.push(make_pair(p.first+rows[i],p.second+columns[i]));
                }
            }
        }
    }

    return dist;

} 

void minDist(vector<int> matrix[],int n,int m) {
    int dist[n][m];
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            if(matrix[i][j]) {
                dist[i][j]=0;
            } else {
                dist[i][j]=bfs(i,j,matrix,n,m);
            }
        }
    }
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            cout<<dist[i][j]<<" ";
        }

    }
}

Agorithm:
1. If matrix[i][j] == 1
      dist[i][j]=0
   else
      dist[i][j]= bfs with source as (i,j)
Olivia Pearls
  • 139
  • 1
  • 11

1 Answers1

1

Your algorithm is not efficient, as each run of BFS "only" results in one cell update.

You should tackle this from a different angle, more like a flood-fill: perform only one BFS traversal, starting with all the nodes that have a 1 in the queue. Then while you extend to cells that do not yet have a known distance, fill it in.

Here is your code adapted to that idea:

void minDist(vector<int> matrix[],int n,int m) {
    int dist[n][m];
    vector<pair<int,int>> q; // in this method, we have enough with vector

    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            if(matrix[i][j]) {
                dist[i][j]=0;
                q.push_back(make_pair(i,j));
            } else {
                dist[i][j]=-1; // undefined distance
            }
        }
    }
    // bfs
    static int rows[]={0,-1,0,1};
    static int columns[]={1,0,-1,0};
    int curdist=1;
    while(!q.empty()) {
        vector<pair<int,int>> q2; // use separate vector for the next extension
        while(!q.empty()) {
            pair<int,int> p=q.back();
            q.pop_back();
            for(int i=0;i<4;i++) {
                if(isSafe(p.first+rows[i],p.second+columns[i],n,m)) {
                    if(dist[p.first+rows[i]][p.second+columns[i]] == -1) {
                        dist[p.first+rows[i]][p.second+columns[i]] = curdist;
                        q2.push_back(make_pair(p.first+rows[i],p.second+columns[i]));
                    }
                }
            }
        }
        q = q2; // Now copy that extension back into the original vector
        curdist++;
    }
    // output
    for(int i=0;i<n;i++) {
        for(int j=0;j<m;j++) {
            cout<<dist[i][j]<<" ";
        }
        cout<<"\n";
    }
}
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I tried solution like yours. Its says time limit exceeded. Please have a look and suggest what's wrong.Here is the long. Here is the link. [link](https://stackoverflow.com/questions/62678092/distance-of-nearest-cell-having-1) – Vivek kumar Jul 13 '20 at 12:55
  • I don't understand: you link to a question where you have *accepted* an answer. So I suppose you don't have that timeout problem. If you still do, then why did you mark that answer as accepted? – trincot Jul 13 '20 at 13:33