#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 h[MAX_V*2+2], dist[MAX_V*2+2];
int prevv[MAX_V*2+2];
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(h, l+r+2, 0);
	while (true) {
		fill_n(dist, l+r+2, INT_INF);
		dist[l+r+1] = 0;
        fill_n(used, l+r+2, false);
        while (true) {
            int v = -1;
            int dist2 = 0;
            int flag;
            for (int i = 0; i < l+1; i++) {
                if (!used[i] && (v == -1 || dist[i] < dist2)){
                    v = i;
                    dist2 = dist[i];
                    flag = true;
                }
            }
            for (int i = 0; i < r+1; i++) {
                if (!used[i+l+1] && (v == -1 || dist[i+l+1] < dist2)){
                    v = i;
                    dist2 = dist[i+l+1];
                    flag = false;
                }
            }
            if (v == -1) break;
            if (flag) {
            	used[v] = true;
	            for (int i = 0; i < r+1; i++) {
					if (!flow[v][i] && dist[i+l+1] > dist[v] + G[v][i] + h[v] - h[i+l+1]) {
						dist[i+l+1] = dist[v] + G[v][i] + h[v] - h[i+l+1];
						prevv[i+l+1] = v;
					}
				}
            } else {
            	used[v+l+1] = true;
	            for (int i = 0; i < l+1; i++) {
					if (flow[i][v] && dist[i] > dist[v+l+1] - G[i][v] + h[v+l+1] - h[i]) {
						dist[i] = dist[v+l+1] - G[i][v] + h[v+l+1] - h[i];
						prevv[i] = v;
					}
				}
            }
        }
		if (dist[l] >= INT_INF) {
			break;
		}
		for (int v = 0; v < l+r+2; v++) {
			h[v] += dist[v];
		}
		res += h[l];
        res += min_f;
		bool flag = true;
		for (int v = l; !(v == r && !flag) ; v = (flag) ? prevv[v] : prevv[v+l+1], flag = !flag) {
			if (flag) {
				flow[v][prevv[v]] = false;
			} else {
				flow[prevv[v+l+1]][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: 1484