#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
	EACH(x,vec) is >> x;
	return is;
}
/*
template<class... T>
ostream& operator<<(ostream& os, tuple<T...>& t) {
	for (size_t i = 0; i < tuple_size< tuple<T...> >::value; ++i) {
		if (i) os << " ";
		os << get<0>(t);
	}
	return os;
}
*/
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
	REP(i,vec.size()) {
		if (i) os << " ";
		os << vec[i];
	}
	return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
	REP(i,vec.size()) {
		if (i) os << endl;
		os << vec[i];
	}
	return os;
}

struct Edge {
	int to, cap, cost, rev;
};

vector< vector<Edge> > G;

void add_edge(int from, int to, int cap, int cost) {
	if (from < 0 || to < 0) return;
	G[from].push_back({to, cap, cost, (int)G[to].size()});
	G[to].push_back({from, 0, -cost, (int)G[from].size()-1});
}

int dist[21000], h[21000] = {0}, prevV[21000], prevE[21000];
ll min_cost_flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		fill(&dist[0], &dist[0]+21000, inf); dist[s] = 0;
		priority_queue<P, vector<P>, greater<P> > Q; Q.push({0, s});
		while ( !Q.empty() ) {
			P p = Q.top(); Q.pop();
			int v = p.second;
			if (p.first > dist[v]) continue;
			for (int i = 0; i < G[v].size(); ++i) {
				Edge& e = G[v][i];
				if (e.cap > 0 && dist[v]+e.cost+h[v]-h[e.to] < dist[e.to]) {
					dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
					prevV[e.to] = v;
					prevE[e.to] = i;
					Q.push({dist[e.to], e.to});
				}
			}
		}
		for (int i = 0; i < G.size(); ++i) h[i] += dist[i];

		if (dist[t] == inf) {
			cout << "ERROR" << endl;
			exit(1);
		}

		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 * h[t];
		for (int v = t; v != s; v = prevV[v]) {
			Edge& e = G[prevV[v]][prevE[v]];
			e.cap -= d;
			G[e.to][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int N; cin >> N;
	vector< vector<int> > W(N, vector<int>(N)); cin >> W;
	vector< vector<int> > E(N, vector<int>(N)); cin >> E;
	vector<string> m(N); cin >> m;
	int s = N*2, t = s+1;
	G.resize(t+1);
	REP(y, N) REP(x, N) {
		ll cost = m[y][x] == '.' ? W[y][x]*2 : 0;
		REP(Y, N) {
			if (Y == y) continue;
			if (m[Y][x] == 'o') {
				cost += E[Y][x];
			}
		}
		REP(X, N) {
			if (X == x) continue;
			if (m[y][X] == 'o') {
				cost += E[y][X];
			}
		}
		add_edge(y, N+x, 1, cost);
	}
	REP(y, N) add_edge(s, y, 1, 0);
	REP(x, N) add_edge(N+x, t, 1, 0);
	int cost = min_cost_flow(s, t, N)/2;
	vector<int> v(N, -1);
	REP(i, N) {
		EACH(e, G[i]) {
			if (e.cap == 0) {
				v[i] = e.to-N;
				break;
			}
		}
	}
	vector<string> mm;
	REP(i, N) {
		string str = "";
		REP(j, N) {
			if (j == v[i]) str += "o";
			else str += ".";
		}
		mm.pb(str);
	}
	int cnt = 0;
	REP(y, N) REP(x, N) {
		if (m[y][x] != mm[y][x]) {
			++cnt;
		}
	}
	cout << cost << endl;
	cout << cnt << endl;
	REP(y, N) REP(x, N) {
		if (m[y][x] != mm[y][x]) {
			cout << y+1 << " " << x+1 << " ";
			if (m[y][x] == '.') {
				cout << "write" << endl;
			}
			else {
				cout << "erase" << endl;
			}
		}
	}
}

Measured memory_bytes: 3488