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

#define REP(i,a,n) for(i=a; i<n; i++)
#define rep(i,n) REP(i,0,n)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define foreach(it,x) for(typeof(x.begin()) it=x.begin(); it!=x.end(); it++)


const int dx[] = {0,1,0,-1};
const int dy[] = {-1,0,1,0};
int W,H,sx,sy, gx, gy;
int bfscost[10][10];
char csize, wsize, wx[3], wy[3], cx[3], cy[3];
char field[16][16];
char DP[9][9][9][9][9][9][9][9];


struct state{
    char x, y, cx[3], cy[3], Sc;

    state(char _x, char _y, char _cx[], char _cy[], char _Sc){
        x = _x, y = _y, Sc = _Sc;
        cx[0] = _cx[0], cx[1] = _cx[1], cx[2] = _cx[2];
        cy[0] = _cy[0], cy[1] = _cy[1], cy[2] = _cy[2];
    }

    bool operator<(const state& a)const{
        if( x != a.x ) return x < a.x;
        if( y != a.y ) return y < a.y;
        if( cx[0] != a.cx[0] ) return cx[0] < a.cx[0];
        if( cx[1] != a.cx[1] ) return cx[1] < a.cx[1];
        if( cx[2] != a.cx[2] ) return cx[2] < a.cx[2];

        if( cy[0] != a.cy[0] ) return cy[0] < a.cy[0];
        if( cy[1] != a.cy[1] ) return cy[1] < a.cy[1];
        if( cy[2] != a.cy[2] ) return cy[2] < a.cy[2];
        return Sc < a.Sc;
    }

    bool operator==(const state& a)const{
        return (x == a.x && y == a.y && 
                (cx[0] == a.cx[0] && cx[1] == a.cx[1] && cx[2] == a.cx[2]) &&
                (cy[0] == a.cy[0] && cy[1] == a.cy[1] && cy[2] == a.cy[2]) &&
                Sc == a.Sc);
    }
};

// (tx,ty) == 'w'
bool isdel(char tx, char ty, char ncx[], char ncy[]){
    int i;
    if( field[ty][tx] != 'w' ) return true;
    rep(i,csize) if( ncx[i] == tx && ncy[i] == ty ) return true;
    return false;
}
bool iscontena(char tx, char ty, char ncx[], char ncy[], char Sc){
    int i;
    rep(i,csize) if( ncx[i] == tx && ncy[i] == ty && !(Sc&(1<<i))) return true;
    return false;
}

void BFS(char nx, char ny, char ncx[], char ncy[], char Sc){
    int i,j,k;

    // init
    memset(bfscost, -1, sizeof(bfscost));

    bfscost[ny][nx] = 0;
    queue<pair<int,int> > q;
    q.push(make_pair(nx,ny));

    while( !q.empty() ){
        int x = q.front().first, y = q.front().second;
        int cost = bfscost[y][x];
        q.pop();

        rep(k,4){
            int tx = x + dx[k];
            int ty = y + dy[k];
            if( field[ty][tx] == '#' || bfscost[ty][tx] != -1 || iscontena(tx,ty,ncx,ncy,Sc) ) continue;
            if( field[ty][tx] == 'w' && !isdel(tx, ty, ncx, ncy) ) continue;

            bfscost[ty][tx] = cost + 1;
            q.push(make_pair(tx,ty));
        }
    }
}


void input(){
    int i,j;

    rep(i,H){
        scanf("%s",field[i]);
        rep(j,W){
            if( field[i][j] == '@' ) sx = j, sy = i;
            if( field[i][j] == 'E' ) gx = j, gy = i;
            if( field[i][j] == 'w' ){
                wx[wsize] = j, wy[wsize] = i;
                wsize++;
            }
            if( field[i][j] == 'c' ){
                cx[csize] = j, cy[csize] = i;
                csize++;
            }
        }
    }
}


int main(){
    int i,j,k;
    //map<state,int> dp;

    while( scanf("%d%d",&H,&W), H|W ){
        // init
        //dp.clear();
        csize = wsize = 0;
        memset(DP,-1,sizeof(DP)); //
        rep(i,3) cx[i] = cy[i] = 0;

        // input
        input();

        int res = INT_MAX;
        priority_queue<pair<int, state>, vector<pair<int,state> >, greater<pair<int,state> > > q;
        q.push(make_pair(0,state(sx,sy,cx,cy,0)));
        DP[cx[0]][cy[0]][cx[1]][cy[1]][cx[2]][cy[2]][sx][sy] = 0; //

        while( !q.empty() ){
            int cost = q.top().first;
            char nx = q.top().second.x, ny = q.top().second.y;
            char tSc = q.top().second.Sc;
            char ncx[3], ncy[3];
            rep(i,3) ncx[i] = ncy[i] = 0;
            rep(i,csize) ncx[i] = q.top().second.cx[i], ncy[i] = q.top().second.cy[i];
            q.pop();

            if( res <= cost ) break;

            // BFS
            BFS(nx, ny, ncx, ncy,tSc);

            if( bfscost[gy][gx] != -1 ) res = min(res, cost + bfscost[gy][gx]);                    

            // ツ個サツ催敖残ツづづづゥツコツδ督テツナツづ個偲シツ暗債づ個マツスツつゥツづァツコツδ督テツナツづーツ督ョツつゥツつキ
            rep(i,csize) if( !(tSc&(1<<i)) ) {
                rep(j,4){
                    int tx = ncx[i] + dx[j];
                    int ty = ncy[i] + dy[j];
                    if( bfscost[ty][tx] == -1 ) continue;

                    // ツ板スツ妥篠陛サツ古シツづ可コツδ督テツナツづーツ督ョツつゥツつキ
                    int ttSc = tSc;
                    int dir = (j + 2) % 4;
                    int tcx = ncx[i], tcy = ncy[i];
                    for(;;){
                        int ay = tcy + dy[dir];
                        int ax = tcx + dx[dir];
                        if( field[ay][ax] == '#' || iscontena(ax,ay,ncx,ncy,tSc) ) break;
                        tcx += dx[dir];
                        tcy += dy[dir];
                        if( field[ay][ax] == 'w' && !isdel(ax,ay,ncx,ncy) ){
                            ttSc |= 1<<i;
                            break;
                        }
                    }
                    // tcx, tcyツつェツコツδ督テツナツつェツ止ツづ慊づつスツ暗環置
                    if( tcx == ncx[i] && tcy == ncy[i] ) continue;

                    char ttcx[3], ttcy[3];
                    rep(k,3) ttcx[i] = ttcy[i] = 0;
                    rep(k,csize) ttcx[k] = ncx[k], ttcy[k] = ncy[k];
                    ttcx[i] = tcx, ttcy[i] = tcy;

                    char*dpp = &DP[ttcx[0]][ttcy[0]][ttcx[1]][ttcy[1]][ttcx[2]][ttcy[2]][tx][ty];
                    if( *dpp == -1 || *dpp > cost + bfscost[ty][tx] ){
                        *dpp = cost + bfscost[ty][tx];
                        q.push(make_pair(cost + bfscost[ty][tx], state(tx,ty,ttcx,ttcy,ttSc)));
                    }
                }
            }
        }

        printf("%d\n", res == INT_MAX ? -1 : res);
    }

    return 0;
}

Measured memory_bytes: 0