#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#include <typeinfo>
#include <queue>
#include <stack>
#include <tuple>

using namespace std;


typedef long long ll;
const int MAX_V = 110;
const int INT_INF = 1<<30;
typedef pair<int, int> P;
typedef tuple<int, int, int> T;
struct edge {
	int cap, cost;
};

int G[MAX_V][MAX_V];
int hl[MAX_V], hr[MAX_V], distl[MAX_V], distr[MAX_V];
int prevvl[MAX_V], prevvr[MAX_V];
bool used[MAX_V*2+2];
bool flow[MAX_V][MAX_V] = {};

int bit_matching_cost(int l, int r) {
    int min_f = 0;
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < r; j++) {
            min_f = min(min_f, G[i][j]);
        }
    }
    for (int i = 0; i < l; i++) {
        for (int j = 0; j < r; j++) {
            G[i][j] -= min_f;
        }
    }    
	for (int i = 0; i < l; i++) {
		G[i][r] = 0;
		flow[i][r] = true;
	}
	for (int i = 0; i < r; i++) {
		G[l][i] = 0;
		flow[l][i] = true;
	}
    G[l][r] = INT_INF;
    flow[l][r] = false;
	int res = 0;
	fill_n(hl, l+1, 0);
	fill_n(hr, r+1, 0);
	while (true) {
		fill_n(distl, l+1, INT_INF);
		fill_n(distr, r+1, INT_INF);
		distr[r] = 0;
        fill_n(used, l+r+2, false);
        while (true) {
            int v = -1;
            int dist = 0;
            int flag;
            for (int i = 0; i < l+1; i++) {
                if (!used[i] && (v == -1 || distl[i] < dist)){
                    v = i;
                    dist = distl[i];
                    flag = true;
                }
            }
            for (int i = 0; i < r+1; i++) {
                if (!used[i+l+1] && (v == -1 || distr[i] < dist)){
                    v = i;
                    dist = distr[i];
                    flag = false;
                }
            }
            if (v == -1) break;
            if (flag) {
            	used[v] = true;
	            for (int i = 0; i < r+1; i++) {
					if (!flow[v][i] && distr[i] > distl[v] + G[v][i] + hl[v] - hr[i]) {
						distr[i] = distl[v] + G[v][i] + hl[v] - hr[i];
						prevvr[i] = v;
					}
				}
            } else {
            	used[v+l+1] = true;
	            for (int i = 0; i < l+1; i++) {
					if (flow[i][v] && distl[i] > distr[v] - G[i][v] + hr[v] - hl[i]) {
						distl[i] = distr[v] - G[i][v] + hr[v] - hl[i];
						prevvl[i] = v;
					}
				}
            }
        }
		if (distl[l] >= INT_INF) {
			break;
		}
		for (int v = 0; v < l+1; v++) {
			hl[v] += distl[v];
		}
		for (int v = 0; v < r+1; v++) {
			hr[v] += distr[v];
		}
		res += hl[l];
        res += min_f;
		bool flag = true;
		for (int v = l; !(v == r && !flag) ; v = (flag) ? prevvl[v] : prevvr[v], flag = !flag) {
			if (flag) {
				flow[v][prevvl[v]] = false;
			} else {
				flow[prevvr[v]][v] = true;
			}
		}
	}
	return res;
}
int cost[MAX_V][MAX_V];


const int MAX_N = 105;
int N;
int W[MAX_N][MAX_N], E[MAX_N][MAX_N];
bool F[MAX_N][MAX_N], F2[MAX_N][MAX_N];

int main(int argc, char *argv[]) {
	cin >> 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++) {
		string s;
		cin >> s;
		for (int j = 0; j < N; j++) {
			F[i][j] = (s[j] == 'o');
		}
	}

    int f = 0;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (F[i][j]) {
				G[i][j] = -E[i][j];
                f += E[i][j];
			} else {
				G[i][j] = W[i][j];
			}
		}
	}
	f += bit_matching_cost(N, N);
	int c = 0;
	vector<T> q;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (F[i][j] != flow[i][j]) {
				c++;
				q.push_back(T(i, j, F[i][j]));
			}
		}
	}
	printf("%d\n%d\n", f, c);
	for (T t: q) {
		printf("%d %d %s\n", get<0>(t)+1, get<1>(t)+1, get<2>(t) ? "erase" : "write");
	} 
    return 0;
}

Measured memory_bytes: 1488