#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
using namespace std;

typedef istringstream ISS;
typedef ostringstream OSS;
typedef vector<string> VS;
typedef char INT;
typedef vector<INT> VI;
typedef vector<VI> VVI;
typedef pair <INT, INT> II;
typedef vector <II> VII;

template<class T> ostream& operator << ( ostream& os, vector<T> v ) {
    for ( typename vector<T>::iterator it_i = v.begin(); it_i != v.end(); ++it_i ) {
        os << *it_i << ", ";
    }
    return os;
}


int W, H;
VS M;
map <II, int> ID;
int CID;

void setCellID( int r, int c ) {
    if ( ID.count( II( r, c ) ) ) return;
    ID[II(r,c)] = CID ++;
}

int getCellID( int r, int c ) {
    return ID[II(r,c)];
}

void init() {
    ID.clear();
    CID = 0;

    for ( int i = 0; i < H; ++ i ) {
        for ( int j = 0; j < W; ++ j ) {
            if ( M[i][j] == '#' ) continue;
            setCellID( i, j );
        }
    }
}

bool input() {
    if ( ! ( cin >> W >> H && W ) ) return false;
    M = VS(H);
    for ( int i = 0; i < H; ++ i ) {
        cin >> M[i];
    }
    return true;
}

typedef pair <II, int> STATE;
typedef pair <int, STATE> NODE; 
typedef queue <NODE> QUEUE;
typedef set <STATE> VISITED;
const int dr[4] = { 0, 0, 1, -1 };
const int dc[4] = { 1, -1, 0, 0 };
char rr[3];
char rc[3];
QUEUE Q;
bool V[51][51][51][51];

STATE getState( int r, int c ) {
    int bitState = 0;
    for ( int i = 0; i < 3; ++ i ) {
        bitState <<= 8;
        bitState |= ((rr[i]-1) << 4) | (rc[i]-1);
    }
    return STATE( II( r, c ), bitState );
}

II deployState( STATE state ) {
    for ( int i = 2; i >= 0; -- i ) {
        rr[i] = ( ( state.second & 0xF0 ) >> 4 ) + 1;
        rc[i] = ( state.second & 0x0F ) + 1;
        state.second >>= 8;
    }
    return state.first;
}

int solve() {
    Q = QUEUE();
    fill( (bool*)V, (bool*)V+51*51*51*51, false );
    char sr, sc;
    int rocks = 0, marks = 0;
    char rr_[3], rc_[3];
    char mr[3], mc[3];

    for ( int i = 0; i < H; ++ i ) {
        for ( int j = 0; j < W; ++ j ) {
            if ( M[i][j] == '@' ) {
                sr = i;
                sc = j;
                M[i][j] = '.';
            } else if ( M[i][j] == '*' ) {
                rr_[rocks] = i;
                rc_[rocks] = j;
                rocks ++;
                M[i][j] = '.';
            } else if ( M[i][j] == '_' ) {
                mr[marks] = i;
                mc[marks] = j;
                marks ++;
                M[i][j] = '.';
            }
        }
    }

    for ( int i = 0; i < 3; ++ i ) {
        rr[i] = rr_[i];
        rc[i] = rc_[i];
    }

    Q.push( NODE( 0, getState( sr, sc ) ) );
    V[getCellID(sr,sc)][getCellID(rr[0],rc[0])][getCellID(rr[1],rc[1])][getCellID(rr[2],rc[2])] = true;

    cin.ignore();
    cin.clear();

    while ( ! Q.empty() ) {
        NODE node = Q.front();
        Q.pop();

        int steps = node.first;
        STATE state = node.second;
        II ret = deployState( state );
        char r = ret.first;
        char c = ret.second;


        bool checked[3];
        fill( checked, checked+3, false );
        for ( int i = 0; i < 3; ++ i ) {
            for ( int j = 0; j < 3; ++ j ) {
                if ( rr[i] == mr[j] && rc[i] == mc[j] ) {
                    checked[j] = true;
                }
            }
        }
        if ( count( checked, checked+3, true ) == 3 ) {
            return steps;
        }

        for ( int i = 0; i < 4; ++ i ) {
            deployState( state );
            int nr = r + dr[i];
            int nc = c + dc[i];
            if ( nr < 0 || nr >= H || nc < 0 || nc >= W ) continue;
            bool flag = false; 
            for ( int j = 0; j < 3; ++ j ) {
                if ( nr == rr[j] && nc == rc[j] ) {
                    int nnr = nr + dr[i];
                    int nnc = nc + dc[i];
                    if ( nnr < 0 || nnr >= H || nnc < 0 || nnc >= W ) {
                        flag = true;
                        break;
                    }
                    if ( M[nnr][nnc] == '#' ) {
                        flag = true;
                        break;
                    }
                    for ( int k = 0; k < 3; ++ k ) {
                        if ( nnr == rr[k] && nnc == rc[k] ) {
                            flag = true;
                            break;
                        }
                    }
                    if ( flag ) break;
                    rr[j] = nnr;
                    rc[j] = nnc;
                    break;
                }
            }
            if ( flag ) continue;
            if ( M[nr][nc] == '#' ) continue;
            int nsteps = steps + 1;
            STATE state = getState( nr, nc );
            int a = getCellID(nr,nc);
            int b = getCellID(rr[0],rc[0]);
            int c = getCellID(rr[1],rc[1]);
            int d = getCellID(rr[2],rc[2]);
            if ( V[a][b][c][d] ) continue;
            V[a][b][c][d] = true;
            NODE next( nsteps, state );
            Q.push( next );
        }
    }
    
    return -1;
}

int main() {
    while ( input() ) {
        init();
        cout << solve() << endl;
    }
    return 0;
}

Measured memory_bytes: 8968