#include #include #include #include #include using namespace std; #define FNAME "erythea.txt" #define cin fin ifstream fin(FNAME); #define SIZE_MAX 80 #define NIL (-1) #define INFTY INT_MAX class GridPoint { public: int row, col; GridPoint() {} GridPoint( int row, int col ) : row(row), col(col) {} }; int height, width; bool B[SIZE_MAX][SIZE_MAX]; int GP[SIZE_MAX+1][SIZE_MAX+1]; bool isStrongHoldingWall( int row, int col ) { int nblock = 0; if ( row > 0 && col > 0 && B[row-1][col-1] ) nblock++; if ( row < height && col > 0 && B[row][col-1] ) nblock++; if ( row < height && col < width && B[row][col] ) nblock++; if ( row > 0 && col < width && B[row-1][col] ) nblock++; return (1 <= nblock && nblock < 4); } bool canGoDown( int row, int col ) { if ( row == height ) return false; if ( col == 0 || col == width ) return true; if ( B[row][col] && B[row][col-1] ) return false; return true; } bool canGoUp( int row, int col ) { if ( row == 0 ) return false; if ( col == 0 || col == width ) return true; if ( B[row-1][col] && B[row-1][col-1] ) return false; return true; } bool canGoLeft( int row, int col ) { if ( col == 0 ) return false; if ( row == 0 || row == height ) return true; if ( B[row-1][col-1] && B[row][col-1] ) return false; return true; } bool canGoRight( int row, int col ) { if ( col == width ) return false; if ( row == 0 || row == height ) return true; if ( B[row][col] && B[row-1][col] ) return false; return true; } int computeShortestPath( const GridPoint &src, const GridPoint &dest ) { multimap DQ; int D[SIZE_MAX+1][SIZE_MAX+1]; for ( int r = 0; r <= height; r++ ) for ( int c = 0; c <= width; c++ ) D[r][c] = INFTY; DQ.insert(make_pair(GP[src.row][src.col], src)); while ( !DQ.empty() ) { const int riskSum = DQ.begin()->first; const int row = DQ.begin()->second.row; const int col = DQ.begin()->second.col; DQ.erase(DQ.begin()); if ( riskSum > D[row][col] ) continue; if ( row == dest.row && col == dest.col ) return riskSum; if ( canGoDown(row, col) && D[row+1][col] > riskSum+GP[row+1][col] ) DQ.insert(make_pair(riskSum+GP[row+1][col], GridPoint(row+1, col))), D[row+1][col] = riskSum+GP[row+1][col]; if ( canGoUp(row, col) && D[row-1][col] > riskSum+GP[row-1][col] ) DQ.insert(make_pair(riskSum+GP[row-1][col], GridPoint(row-1, col))), D[row-1][col] = riskSum+GP[row-1][col]; if ( canGoLeft(row, col) && D[row][col-1] > riskSum+GP[row][col-1] ) DQ.insert(make_pair(riskSum+GP[row][col-1], GridPoint(row, col-1))), D[row][col-1] = riskSum+GP[row][col-1]; if ( canGoRight(row, col) && D[row][col+1] > riskSum+GP[row][col+1] ) DQ.insert(make_pair(riskSum+GP[row][col+1], GridPoint(row, col+1))), D[row][col+1] = riskSum+GP[row][col+1]; } return INFTY; } int main() { int ntest; cin >> ntest; for ( int nt = 0; nt < ntest; nt++ ) { cin >> height >> width; GridPoint source; cin >> source.row >> source.col; GridPoint destination; cin >> destination.row >> destination.col; char bin; for ( int r = 0; r < height; r++ ) for ( int c = 0; c < width; c++ ) cin >> bin, B[r][c] = (bin == '0')? false : true; for ( int r = 0; r <= height; r++ ) for ( int c = 0; c <= width; c++ ) GP[r][c] = NIL; queue Q; for ( int r = 0; r <= height; r++ ) for ( int c = 0; c <= width; c++ ) if ( isStrongHoldingWall(r, c) ) Q.push(GridPoint(r, c)), GP[r][c] = height+width; for ( int risk = height+width; !Q.empty(); risk-- ) for ( int size = Q.size(); size > 0; size-- ) { const int row = Q.front().row; const int col = Q.front().col; Q.pop(); if ( canGoDown(row, col) && GP[row+1][col] == NIL ) Q.push(GridPoint(row+1, col)), GP[row+1][col] = risk-1; if ( canGoUp(row, col) && GP[row-1][col] == NIL ) Q.push(GridPoint(row-1, col)), GP[row-1][col] = risk-1; if ( canGoLeft(row, col) && GP[row][col-1] == NIL ) Q.push(GridPoint(row, col-1)), GP[row][col-1] = risk-1; if ( canGoRight(row, col) && GP[row][col+1] == NIL ) Q.push(GridPoint(row, col+1)), GP[row][col+1] = risk-1; } const int result = computeShortestPath(source, destination); if ( result == INFTY ) cout << "no solution" << endl; else cout << result << endl; } return 0; }