#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const ll inf = 1e14;

class min_cost_flow{
public:
    int N;
    struct edge{int to; ll cap,cost; int rev; bool is_rev;};
    vector<vector<edge>> G;
    vector<ll> h,dist,prevv,preve;
    min_cost_flow(int n){
        N = n;
        G = vector<vector<edge>>(N);
        h = dist = prevv = preve = vector<ll>(N,0);
    }
    void add_edge(int from,int to,ll cap,ll cost){
        G[from].push_back((edge){to,cap,cost,(int) G[to].size(),false});
        G[to].push_back((edge){from,0,-cost,(int) G[from].size()-1,true});
    }
    ll answer(int s,int t,ll f){
        ll res = 0;
        fill(h.begin(),h.end(),0);
        while(f>0){
            priority_queue<P,vector<P>,greater<P>> Q;
            fill(dist.begin(),dist.end(),inf);
            dist[s] = 0;
            Q.push(P(s,0));
            while(!Q.empty()){
                P p = Q.top(); Q.pop();
                int v = p.second;
                if(dist[v]<p.first) 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+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<N;v++) h[v] += dist[v];
            ll d = f;
            for(int v=t;v!=s; v=prevv[v]){
                d = min(d,G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            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 main(){
    int N;
    cin >> N;
    vector<vector<ll>> W(N+1,vector<ll>(N+1,0)),E(N+1,vector<ll>(N+1,0));
    vector<vector<char>> F(N+1,vector<char>(N+1,0));
    for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) cin >> W[i][j];
    for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) cin >> E[i][j];
    min_cost_flow flow(2*N+2);
    ll sum = 0;
    for(int i=1;i<=N;i++) for(int j=1;j<=N;j++){
        cin >> F[i][j];
        if(F[i][j]=='o'){
            flow.add_edge(i,N+j,1,-E[i][j]);
            sum += E[i][j];
        }else{
            flow.add_edge(i,N+j,1,W[i][j]);
        }
    }
    for(int i=1;i<=N;i++){
        flow.add_edge(0,i,1,0);
        flow.add_edge(i+N,2*N+1,1,0);
    }
    ll res = flow.answer(0,2*N+1,N);
    cout << sum+res << endl;
    struct operation{
        int x,y;
        string op;
    };
    vector<operation> ans;
    for(int i=N+1;i<=2*N;i++){
        for(auto& x:flow.G[i]){
            if(x.is_rev){
                if(x.cost>0 && x.cap==0){
                    ans.push_back({x.to,i-N,"erase"});
                }else if(x.cost<0 && x.cap==1){
                    ans.push_back({x.to,i-N,"write"});
                }
            }
        }
    }
    cout << (int) ans.size() << endl;
    for(auto& x:ans) cout << x.x << " " << x.y << " " << x.op << endl;
}


Measured memory_bytes: 4248