#include <bits/stdc++.h>
#define MAX_V 300
#define INF 1e9
using namespace std;

/*????°??????¨???(???????????£????????????????????¨) O(F|V||E|)*/
//????????¨????§???????(???????????????????????????????????????)
struct edge{int to, cap,cost,rev;};
int V;                         //????????°
vector<edge> G[MAX_V];         //??°???????????£??\???????????¨???
int dist[MAX_V];               //???????????¢
int prevv[MAX_V],preve[MAX_V]; //??´??????????????¨???

// from??????to??????????????????cap????????????cost???????????°????????????????????????
void add_edge(int from,int to,int cap,int cost){
  G[from].push_back((edge){to,cap,cost,G[to].size()});
  G[to].push_back((edge){from,0,-cost,G[from].size()-1});
}

//s??????t????????????f???????°??????¨???????±???????
//??????????????´???-1?????????
int min_cost_flow(int s,int t,int f){
  int res=0;
  while(f>0){
    //????????????????????????????????????,s-t????????????????±???????
    fill(dist,dist+V,INF);
    dist[s]=0;
    bool update = true;
    while(update){
      update = false;
      for(int v=0; v<V ;v++){
	if(dist[v]==INF) continue;
	for(int i=0; i<G[v].size(); i++){
	  edge &e = G[v][i];
	  if(e.cap > 0 && dist[e.to] > dist[v]+e.cost) {
	    dist[e.to] = dist[v] + e.cost;
	    prevv[e.to] = v;
	    preve[e.to] = i;
	    update = true;
	  }
	}
      }
    }
    if(dist[t]==INF) return -1; //????????\??????????????????
    
    //s???t?????????????????£??????????????????
    int d = f;
    for(int v=t; v!=s; v=prevv[v])d=min(d,G[prevv[v]][preve[v]].cap);
    f -= d;
    res += d*dist[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 can[MAX_V][MAX_V]; //can[i][j]:=???????????\??????i?????????j??????????????????
int Biparite_Matching(int N,int K){
  //0??????N-1: ???????????\???????????????????????????
  //N??????N+K-1: ???????????????????????????
  int s = N+K, t = s+1;

  //s??¨???????????\??????????????¶
  for(int i=0; i<N; i++) add_edge(s,i,1,0);
  
  //????????¨t?????????
  for(int i=0; i<K; i++) add_edge(N+i,t,1,0);
  
  //???????????\????????¨??????????????¶
  for(int i=0;i<N;i++)
    for(int j=0;j<K;j++)add_edge(i, N+j , 1, can[i][j]);
  V=N+K+2;
  return min_cost_flow(s,t,N);
}


int main(){
  int n;
  cin>>n;
  int W[101][101],E[101][101];
  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];
  
  string mp[101];
  for(int i=0;i<n;i++)cin>>mp[i];
  
  int sumW[101]={},sumH[101]={},sum=0;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++){
      if(mp[i][j]=='o') sumW[i]+=E[i][j],sum+=E[i][j];
      if(mp[j][i]=='o') sumH[i]+=E[j][i];
    }


  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++){
      int cost=sumH[j]+sumW[i];
      //if(mp[i][j]=='o') cost-=2*E[i][j];
      //if(mp[i][j]=='.') cost+=W[i][j];
      if(mp[i][j]=='o') cost=-E[i][j];
      if(mp[i][j]=='.') cost=W[i][j];
      can[i][j]=cost;

    }
  cout<<sum+Biparite_Matching(n,n)<<endl;
  
  bool used[101][101]={};
  for(int i=0;i<n;i++) 
    for(int j=0;j<G[i].size();j++)
      if(G[i][j].cap<=0)used[i][G[i][j].to-n]=1;
  

  int mincost=0,cnt=0;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++) 
      if(used[i][j]&&mp[i][j]=='.')cnt++,mincost+=W[i][j];
      else if(!used[i][j]&&mp[i][j]=='o')cnt++,mincost+=E[i][j];

  //  cout<<mincost<<endl;
  cout<<cnt<<endl;
  for(int i=0;i<n;i++)
    for(int j=0;j<n;j++) 
      if(used[i][j]&&mp[i][j]=='.')cout<<i+1<<" "<<j+1<<" write"<<endl;
      else if(!used[i][j]&&mp[i][j]=='o')cout<<i+1<<" "<<j+1<<" erase"<<endl;
  
  return 0;
}

Measured memory_bytes: 3620