#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

struct Edge {
  int src, dst, capacity, cost, rev;
  Edge(int src, int dst, int capacity, int cost)
    : src(src), dst(dst), capacity(capacity), cost(cost) {}
  Edge(int src, int dst, int capacity, int cost, int rev)
    : src(src), dst(dst), capacity(capacity), cost(cost), rev(rev) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.cost != f.cost ? e.cost > f.cost :
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<int> Array;
typedef vector<Array> Matrix;

void add_edge(Graph &g, int s, int d, int cost, int cap) {
  g[s].push_back(Edge(s,d,cap,cost));
  g[d].push_back(Edge(d,s,0,-cost));
  //cout<<s<<" "<<d<<" "<<cost<<" "<<cap<<endl;
}

#define RESIDUE(u,v) (capacity[u][v]-flow[u][v])
#define RCOST(u,v) (cost[u][v] + h[u] - h[v])

int sum;
pair<int, int> minimumCostFlow(Graph &g, int s, int t) {
  const int n = g.size();
  const int inf = 1<<29;
  Matrix capacity(n, Array(n)), cost(n, Array(n)), flow(n, Array(n));
  for (int u=0; u<n; ++u) {
    for (Edges::iterator e = g[u].begin(); e != g[u].end(); ++e) {
      capacity[e->src][e->dst] += e->capacity;
      cost[e->src][e->dst] += e->cost;
    }
  }

  pair<int,int> total = make_pair(0,0);
  vector<int> h(n, inf);
  h[s] = 0;
  for (int k=0; k<n; ++k)
    for (int i=0; i<n; ++i)
      for (Edges::iterator e=g[i].begin(); e!=g[i].end(); ++e)
        if (capacity[e->src][e->dst])
          h[e->dst] = min(h[e->dst], h[e->src] + cost[e->src][e->dst]);

  for (int F = inf; F > 0; ) {
    vector<int> d(n, inf); d[s] = 0;
    vector<int> p(n, -1);
    priority_queue<Edge> Q;
    for (Q.push(Edge(-2,s,0,0)); !Q.empty(); ) {
      Edge e = Q.top(); Q.pop();
      if (p[e.dst] != -1) continue;
      p[e.dst] = e.src;
      for (Edges::iterator f=g[e.dst].begin(); f != g[e.dst].end(); ++f) {
        if (RESIDUE(f->src, f->dst) > 0) {
          if (d[f->dst] > d[f->src] + RCOST(f->src, f->dst)) {
            d[f->dst] = d[f->src] + RCOST(f->src, f->dst);
            Q.push(Edge(f->src, f->dst, 0, d[f->dst]));
          }
        }
      }
    }

    if (p[t] == -1) break;
    int f = F;
    for (int u=t; u!=s; u=p[u]) f = min(f, RESIDUE(p[u], u));
    for (int u=t; u!=s; u=p[u]) {
      total.first += f * cost[p[u]][u];
      flow[p[u]][u] += f; flow[u][p[u]] -= f;
    }
    F -= f;
    total.second += f;
    for(int u=0; u<n; ++u) if (h[u] != inf) h[u] += d[u];
  }
  cout<<total.first+sum<<endl;
  int cnt = 0;
  int nn = (n-2)/2;
  vector<pair<int,pair<int,int> > > v;
  for (int i=0; i<nn; ++i) {
    for (int j=0; j<nn; ++j) {
      if (flow[i][j+nn] > 0 && cost[i][j+nn] > 0) {
        cnt++;
        v.push_back(make_pair(1, make_pair(i+1,j+1)));
      }
      if (flow[i][j+nn] == 0 && cost[i][j+nn] < 0) {
        cnt++;
        v.push_back(make_pair(0, make_pair(i+1,j+1)));
      }
    }
  }
  cout<<cnt<<endl;
  for (int i=0; i<v.size(); ++i) {
    cout<<v[i].second.second<<" "<<v[i].second.first<<" ";
    if (v[i].first) cout<<"write"<<endl;
    else cout<<"erase"<<endl;
  }
  return total;
}

int w[101][101], e[101][101];
string f[101];

int main() {
  int n;
  while(cin>>n) {
    for (int i=0; i<n; ++i) for(int j=0; j<n; ++j) cin>>w[i][j];
    for (int i=0; i<n; ++i) for(int j=0; j<n; ++j) cin>>e[i][j];
    for (int i=0; i<n; ++i) cin>>f[i];
    Graph g(n*2+2);
    sum = 0;
    for (int i=0; i<n; ++i) add_edge(g, n*2, i, 0, 1);
    for (int i=0; i<n; ++i) add_edge(g, i+n, n*2+1, 0, 1);
    for (int x=0; x<n; ++x) {
      for (int y=0; y<n; ++y) {
        if (f[y][x] == 'o') {
          add_edge(g, x, y+n, -e[y][x], 1);
          sum += e[y][x];
        } else {
          add_edge(g, x, y+n, w[y][x], 1);
        }
      }
    }

    pair<int,int> ans = minimumCostFlow(g, n*2, n*2+1);
  }
}

Measured memory_bytes: 2424