#include <cstdio> #include <queue> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <string> #define INF 10000 using namespace std; int location,target; vector<vector<int> > dp; int h,w; int graph[200][200]; string str[60]; struct POINT{ int x,y; }; POINT pp[3030]; POINT src,tr; int k; int dirx[4]={1,0,0,-1}; int diry[4]={0,1,-1,0}; int bfs(int s,int t) { int tmpy,tmpx; queue<int> q; bool visit[55][55]; int dist[55][55]; memset(dist,0,sizeof(dist)); for(int i=0;i<55;i++) { for(int j=0;j<55;j++) { dist[i][j]=INF; visit[i][j]=false; } } tmpx = pp[s].x; tmpy = pp[s].y; q.push(tmpx); q.push(tmpy); visit[tmpx][tmpy]=1; dist[tmpx][tmpy]=0; while(!q.empty()) { int a = q.front();q.pop(); int b = q.front();q.pop(); for(int i=0;i<4;i++) { int tx = a+dirx[i]; int ty = b+diry[i]; if(tx<0 || tx>=h) continue; if(ty<0 || ty>=w) continue; if(str[tx][ty]=='#') continue; if(!visit[tx][ty]) { q.push(tx);q.push(ty); visit[tx][ty]=1; dist[tx][ty]=dist[a][b]+1; } } } return dist[pp[t].x][pp[t].y]; } int tsp(int status,int location) { if(dp[status][location]!=-1) return dp[status][location]; dp[status][location] = 1e9; int mask = 1<<location; for(int i=0;i<k;i++) { if(i!=location && (status & (1<<i))) dp[status][location]= min(dp[status][location],tsp(status-mask,i)+graph[i][location]); } return dp[status][location]; } int main() { int dx[8]={1,0,0,-1,1,1,-1,-1}; int dy[8]={0,1,-1,0,1,-1,-1,1}; while(cin>>h) { cin>>w; if(h+w==0) break; for(int i=0;i<h;i++) cin>>str[i]; memset(graph,0,sizeof(graph)); int res = 0; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { if(str[i][j]=='~') { str[i][j]='#'; } else if(str[i][j]=='*') { str[i][j]='#'; for(int l=0;l<8;l++) { if(i+dx[l]<0 || i+dx[l]>=h) continue; if(j+dy[l]<0 || j+dy[l]>=w) continue; if(str[i+dx[l]][j+dy[l]]=='!' || str[i+dx[l]][j+dy[l]]=='@') res = -1; if(str[i+dx[l]][j+dy[l]]!='*') str[i+dx[l]][j+dy[l]]='#'; } } } } if(res==-1) { cout<<-1<<"\n"; continue; } k = 0; location = -1; target = -1; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { if(str[i][j]=='!') { pp[k].x = i; pp[k].y = j; k+=1; } else if(str[i][j]=='@') { location = k; pp[k].x = i; pp[k].y = j; k+=1; } } } if(k==1) { cout<<0<<"\n"; continue; } for(int i=0;i<k;i++) { for(int j=i+1;j<k;j++) { graph[i][j]=bfs(i,j); graph[j][i] = graph[i][j]; } } dp = vector< vector< int > >(1<<k,vector<int>(k,-1)); for(int i=0;i<k;i++) dp[1<<i][i]=graph[location][i]; res = tsp((1<<(k))-1,location); if(res>=INF) { cout<<-1<<"\n"; continue; } cout<<res<<"\n"; } return 0; }