#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < int(Y);++(X))
#define rrep(X,Y) for (int (X) = int(Y-1);(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < int(Y);++(X))
#define peat(X,Y) for (;(X) < int(Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define int ll

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef int Cost;
struct Edge{int to,cap,rev;Cost cost;};
typedef vector<Edge> Edges;
typedef vector<vector<Edge> > Graph;

void add_edge(Graph &g,int from,int to,int cap,Cost cost=0){
  g[from].pb((Edge){to,cap,g[to].size(),cost});
  g[to].pb((Edge){from,0,g[from].size()-1,-cost});
}
Cost INF=1e7;

//min-cost,dij

typedef pair<Cost,int> Que;

int V;

//f流せなければINF
Cost min_cost_flow(Graph &g,int s,int t,int f){
  int V=g.size(),res=0;
  vector<Cost> h(V,0),d(V);
  vector<int> prevv(V),preve(V);
  while(f>0){
    priority_queue<Que,vector<Que>,greater<Que> > que;
    int V=g.size();
    d.resize(V);
    fill(all(d),INF);
    d[s]=0;
    que.push(Que(0,s));
    while(!que.empty()){
      Que p=que.top();que.pop();
      int v=p.Y;
      if(d[v]<p.X)continue;
      rep(i,g[v].size()){
        Edge &e=g[v][i];
        if(e.cap>0 && d[e.to]>d[v]+e.cost+h[v]-h[e.to]){
          d[e.to]=d[v]+e.cost+h[v]-h[e.to];
          prevv[e.to]=v;
          preve[e.to]=i;
          que.push(Que(d[e.to],e.to));
        }
      }
    }
    if(d[t] == INF){
      return INF;
    }
    rep(v,V)
      h[v]+=d[v];
    int flow=f;
    for(int v=t;v!=s;v=prevv[v]){
      flow=min(flow,g[prevv[v]][preve[v]].cap);
    }
    f-=flow;
    res+=flow*h[t];
    for(int v=t;v!=s;v=prevv[v]){
      Edge &e=g[prevv[v]][preve[v]];
      e.cap-=flow;
      g[v][e.rev].cap+=flow;
    }
  }
  return res;
}

signed main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int i,j,k,n;
  cin>>n;
  vector<vector<int> > w(n,vector<int>(n)),e(n,vector<int>(n));
  rep(i,n)rep(j,n)
    cin>>w[i][j];
  rep(i,n)rep(j,n)
    cin>>e[i][j];
  string str,strs[n];
  Graph g(n*2+2);
  rep(i,n){
    cin>>str;
    strs[i]=str;
    int sum=0;
    rep(j,n){
      if(str[j]=='o'){
        w[i][j]=-e[i][j];
        sum+=e[i][j];
      }
    }
    rep(j,n)
      add_edge(g,i+2,j+n+2,1,sum+w[i][j]);
    add_edge(g,0,i+2,1,0);
    add_edge(g,i+n+2,1,1,0);
  }
  cout<<min_cost_flow(g,0,1,n)<<endl;
  vector<pii> er,wr;
  rep(i,n){
    int fr=-1;
    rep(j,g[i+n+2].size()){
      if(g[i+n+2][j].cap){
        fr=g[i+n+2][j].to-2;
        break;
      }
    }
    rep(j,n){
      if(j==i){
        if(strs[fr][j]=='.')
          wr.pb(pii(fr,j));
      }else{
        if(strs[fr][j]=='o')
          er.pb(pii(fr,j));
      }
    }
  }
  cout<<er.size()+wr.size()<<endl;
  rep(i,er.size())
    cout<<er[i].X+1<<" "<<er[i].Y+1<<" erase"<<endl;
  rep(i,wr.size())
    cout<<wr[i].X+1<<" "<<wr[i].Y+1<<" write"<<endl;
  return 0;
}

Measured memory_bytes: 2368