#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 220

enum Type{
	ADD,
	DELETE,
};

struct Edge{
	Edge(int arg_to,int arg_capacity,int arg_cost,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		cost = arg_cost;
		rev_index = arg_rev_index;
	}

	int to,capacity,cost,rev_index;
};

struct Info{
	Info(int arg_row,int arg_col,Type arg_type){
		row = arg_row;
		col = arg_col;
		type = arg_type;
	}
	int row,col;
	Type type;
};


int V;
vector<Edge> G[NUM];
int dist[NUM];
int pre_node[NUM],pre_edge[NUM];
int N;
int W[NUM][NUM],E[NUM][NUM];
int row_index[NUM],col_index[NUM];
char table[NUM][NUM+1];


void add_edge(int from,int to,int capacity,int cost){
	G[from].push_back(Edge(to,capacity,cost,G[to].size()));
	G[to].push_back(Edge(from,0,-cost,G[from].size()-1));
}


int min_cost_flow(int source,int sink,int flow){
	int ret = 0;
	while(flow > 0){
		for(int i = 0; i < V; i++)dist[i] = BIG_NUM;
		dist[source] = 0;
		bool update = true;
		while(update){
			update = false;
			for(int node_id = 0; node_id < V; node_id++){
				if(dist[node_id] == BIG_NUM)continue;
				for(int i = 0; i < G[node_id].size(); i++){
					Edge &e = G[node_id][i];
					if(e.capacity > 0 && dist[e.to] > dist[node_id]+e.cost){
						dist[e.to] = dist[node_id]+e.cost;
						pre_node[e.to] = node_id;
						pre_edge[e.to] = i;
						update = true;
					}
				}
			}
		}

		if(dist[sink] == BIG_NUM){
			return -1;
		}

		int tmp_flow = flow;
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			tmp_flow = min(tmp_flow,G[pre_node[node_id]][pre_edge[node_id]].capacity);
		}
		flow -= tmp_flow;
		ret += tmp_flow*dist[sink];
		for(int node_id = sink; node_id != source; node_id = pre_node[node_id]){
			Edge &e = G[pre_node[node_id]][pre_edge[node_id]];
			e.capacity -= tmp_flow;
			G[node_id][e.rev_index].capacity += tmp_flow;
		}
	}
	return ret;
}

int main(){

	scanf("%d",&N);

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++)scanf("%d",&W[row][col]);
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++)scanf("%d",&E[row][col]);

	}

	int sum_cost = 0;
	for(int row = 0; row < N; row++){
		scanf("%s",table[row]);
		for(int col = 0; col < N; col++){
			if(table[row][col] == 'o'){
				sum_cost += E[row][col];
			}
		}
	}

	int source = 0,sink = 1,index = 2;
	for(int i = 0; i < N; i++){
		row_index[i] = index;
		add_edge(source,row_index[i],1,0);
		index++;
	}
	for(int i = 0; i < N; i++){
		col_index[i] = index;
		add_edge(col_index[i],sink,1,0);
		index++;
	}

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			if(table[row][col] == 'o'){
				add_edge(row_index[row],col_index[col],1,-E[row][col]);
			}else{
				add_edge(row_index[row],col_index[col],1,W[row][col]);
			}
		}
	}

	V = index;

	int add_cost = min_cost_flow(source,sink,N);

	printf("%d\n",sum_cost+add_cost);

	int count = 0;

	queue<Info> Q;

	int col;

	for(int row = 0; row < N; row++){
		for(int i = 0; i < G[row_index[row]].size(); i++){
			col = G[row_index[row]][i].to-col_index[0];
			if(col < 0)continue;
			if(table[row][col] == 'o' && G[row_index[row]][i].capacity == 1){
				Q.push(Info(row,col,DELETE));
				count++;
			}else if(table[row][col] == '.' && G[row_index[row]][i].capacity == 0){
				Q.push(Info(row,col,ADD));
				count++;
			}
		}
	}

	printf("%d\n",count);

	while(!Q.empty()){

		printf("%d %d ",Q.front().row+1,Q.front().col+1);
		if(Q.front().type == ADD){
			printf("write\n");
		}else{
			printf("erase\n");
		}

		Q.pop();
	}

	return 0;
}




Measured memory_bytes: 3716