#include <bits/stdc++.h>

using namespace std;

const int MAX_V = 111*2;

typedef pair<int,int> P;
struct D {
  int x,y,t;
};
struct edge {
  int to,cap,cost,rev,f;
  D d;
};
int V;
vector<edge> G[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];
const int inf = 1<<28;
 
void add_edge(int f,int t,int cap,int cost,D d)
{
  G[f].push_back((edge){t,cap,cost,(int)G[t].size(),1,d});
  G[t].push_back((edge){f,0,-cost,(int)G[f].size()-1,0,d});
}

int min_cost_flow(int s,int t,int f)
{
  int res = 0;
  fill(h,h+V,0);
  //printf("%d %d %d\n",s,t,f);
  while( f > 0 ) {
    priority_queue<P,vector<P>,greater<P> > q;
    fill(dist,dist+V,inf);
    dist[s]=0;
    q.push(P(0,s));
    while(!q.empty()) {
      P p = q.top(); q.pop();
      int v = p.second;
      if( dist[v] < p.first ) continue;
      for( int i = 0; i < int(G[v].size()); i++ ) {
        edge& e = G[v][i];
        if( e.cap > 0 && dist[e.to] > dist[v]+e.cost+h[v]-h[e.to] ) {
          dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
          prevv[e.to] = v;
          preve[e.to] = i;
          q.push(P(dist[e.to],e.to));
        }
      }
    }
    if( dist[t] == inf ) {
      return -1;
    }
    for( int v = 0; v < V; v++ ) h[v] += dist[v];
    int d = f;
    for( int v = t; v != s; v = prevv[v] ) {
      d = min(d,G[prevv[v]][preve[v]].cap);
    }
    f -= d;
    //printf("%d %d\n",d,f);
    res += d*h[t];
    for( int v = t; v != s; v = prevv[v] ) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }
  return res;
}

int n,w[111][111],e[111][111];
char f[111][111];

int main(void)
{
  scanf("%d",&n);
  for( int i = 0; i < n; i++ ) {
    for( int j = 0; j < n; j++ ) scanf("%d",w[i]+j);
  }
  for( int i = 0; i < n; i++ ) {
    for( int j = 0; j < n; j++ ) scanf("%d",e[i]+j);
  }
  for( int i = 0; i < n; i++ ) {
    for( int j = 0; j < n; j++ ) scanf(" %c",f[i]+j);
  }
  for( int i = 0; i < n; i++ ) {
    add_edge(n+n,i,1,0,(D){-1,-1,-1});
    add_edge(n+i,n+n+1,1,0,(D){-1,-1,-1});
    for( int j = 0; j < n; j++ ) {
      int s = 0;
      if( f[i][j] == '.' ) s += w[i][j];
      for( int jj = 0; jj < n; jj++ ) {
        if( jj != j && f[i][jj] == 'o' ) {
          s += e[i][jj];
        }
      }
      for( int ii = 0; ii < n; ii++ ) {
        if( ii != i && f[ii][j] == 'o' ) {
          s += e[ii][j];
          s -= e[ii][j];
        }
      }
      //printf("%d ",s);
      add_edge(i,n+j,1,s,(D){j,i,f[i][j]=='.'});
    }
    //puts("");
  }
  V=n+n+2;
  int res = min_cost_flow(n+n,n+n+1,n);
  printf("%d\n",res);
  vector<string> vv;
  char buf[222];
  static bool done[111][111] = {};
  for( int i = 0; i < n+n; i++ ) {
    for( int j = 0; j < int(G[i].size()); j++ ) {
      edge &e = G[i][j];
      if( e.f && e.cap == 0 && e.d.x>=0 ) {
        //printf("%d %d %d\n",e.d.x,e.d.y,e.d.t);
        if( f[e.d.y][e.d.x] == '.' ) {
          sprintf(buf,"%d %d write\n",e.d.y+1,e.d.x+1);
          vv.push_back(buf);
        }
        done[e.d.y][e.d.x] = true;
        for( int ii = 0; ii < n; ii++ ) {
          if( !done[e.d.y][ii] && f[e.d.y][ii] == 'o' ) {
            done[e.d.y][ii] = true;
            sprintf(buf,"%d %d erase\n",e.d.y+1,ii+1);
            vv.push_back(buf);
          }
          if( !done[ii][e.d.x] && f[ii][e.d.x] == 'o' ) {
            done[ii][e.d.x] = true;
            sprintf(buf,"%d %d erase\n",ii+1,e.d.x+1);
            vv.push_back(buf);
          }
        }
        //printf("%d %d write\n",e.d.x+1,e.d.y+1,e.d.t?"erase":"write");
      }
    }
  }
  printf("%d\n",vv.size());
  for( int i = 0; i < int(vv.size()); i++ ) printf("%s",vv[i].c_str());
  return 0;
}

Measured memory_bytes: 2304