#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key

typedef long long ll;
typedef pair<ll,ll> ii;
typedef vector<int> vi;
typedef long double ld; 
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef set<int>::iterator sit;
typedef vector<int>::iterator vit;

struct Edge{
    int u, v;
    long long cap, cost;
 
    Edge(int _u, int _v, long long _cap, long long _cost){
        u = _u; v = _v; cap = _cap; cost = _cost;
    }
};

const ll INF = ll(1e9);
struct MinCostFlow{
    int n, s, t;
    long long flow, cost;
    vector<vector<int> > graph;
    vector<Edge> e;
    vector<bool> me;
    vector<long long> dist, potential;
    vector<int> parent;
    bool negativeCost;
 
    MinCostFlow(int _n){
        // 0-based indexing
        me.assign(_n, 0);
        n = _n;
        graph.assign(n, vector<int> ());
        negativeCost = false;
    }
 
    void addEdge(int u, int v, long long cap, long long cost, bool directed = true){
        if(cost < 0)
            negativeCost = true;
 
        graph[u].push_back(e.size());
        e.push_back(Edge(u, v, cap, cost));
 
        graph[v].push_back(e.size());
        e.push_back(Edge(v, u, 0, -cost));
        if(!directed)
            addEdge(v, u, cap, cost, true);
    }
 
    pair<long long, long long> getMinCostFlow(int _s, int _t){
        s = _s; t = _t;
        flow = 0, cost = 0;
 
        potential.assign(n, 0);
        if(negativeCost){
            // run Bellman-Ford to find starting potential
            dist.assign(n, 1LL<<62);
            for(int i = 0, relax = false; i < n && relax; i++, relax = false){
                for(int u = 0; u < n; u++){
                    for(int k = 0; k < graph[u].size(); k++){
                        int eIdx = graph[u][i];
                        int v = e[eIdx].v, cap = e[eIdx].cap, w = e[eIdx].cost;
 
                        if(dist[v] > dist[u] + w && cap > 0){
                            dist[v] = dist[u] + w;
                            relax = true;
            }   }   }   }
 
            for(int i = 0; i < n; i++){
                if(dist[i] < (1LL<<62)){
                    potential[i] = dist[i];
        }   }   }
 
        while(dijkstra()){
            flow += sendFlow(t, 1LL<<62);
        }
 
        return make_pair(flow, cost);
    }
 
    bool dijkstra(){
        parent.assign(n, -1);
        dist.assign(n, 1LL<<62);
        priority_queue<ii, vector<ii>, greater<ii> > pq;
 
        dist[s] = 0;
        pq.push(ii(0, s));
 
 
        while(!pq.empty()){
            int u = pq.top().second;
            long long d = pq.top().first;
            pq.pop();
 
            if(d != dist[u]) continue;
 
            for(int i = 0; i < graph[u].size(); i++){
                int eIdx = graph[u][i];
                int v = e[eIdx].v, cap = e[eIdx].cap;
                int w = e[eIdx].cost + potential[u] - potential[v];
 
                if(dist[u] + w < dist[v] && cap > 0){
                    dist[v] = dist[u] + w;
                    parent[v] = eIdx;
 
                    pq.push(ii(dist[v], v));
        }   }   }
 
        // update potential
        for(int i = 0; i < n; i++)
        {
            if(dist[i] < (1LL<<62))
                potential[i] += dist[i];
        }
 
        return dist[t] != (1LL<<62);
    }
	
	void dfs(int s)
	{
		me[s]=1;
		//cerr<<s<<'\n';
		for(int i = 0; i < graph[s].size(); i++)
		{
			 int eIdx = graph[s][i];
             int v = e[eIdx].v; ll cap = e[eIdx].cap;
             if(cap==0) continue;
             if(!me[v])
             {
				 dfs(v);
			 }
		}
	}
    long long sendFlow(int v, long long curFlow){
        if(parent[v] == -1)
            return curFlow;
        int eIdx = parent[v];
        int u = e[eIdx].u, w = e[eIdx].cost;
 
        long long f = sendFlow(u, min(curFlow, e[eIdx].cap));
 
        cost += f*w;
        e[eIdx].cap -= f;
        e[eIdx^1].cap += f;
 
        return f;
    }
};

int n, m;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int inid(int x, int y)
{
	return 2*(x*m+y);
}

int outid(int x, int y)
{
	return 2*(x*m+y)+1;
}

MinCostFlow mcmf(5111);

bool isvalid(int x, int y)
{
	if(x>=0&&x<n&&y>=0&&y<m) return 1;
	return 0;
}
int E[51][51];
bool good[51][51];

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	int X, Y;
	cin>>n>>m>>X>>Y;
	int s = 2*m*n; int e = 2*m*n+1;
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < m; j++)
		{
			ll p; cin >> p;
			if(X-1==i&&Y-1==j) p = INF;
			//cerr<<"SQUARE : "<<inid(i,j)<<' '<<outid(i,j)<<' '<<p<<'\n';
			E[i][j] = mcmf.e.size();
			mcmf.addEdge(inid(i,j),outid(i,j),p,0);
			if(p==INF)
			{
				mcmf.addEdge(outid(i,j),e,INF,0);
			}
		}
	}
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < m; j++)
		{
			for(int k = 0; k < 4; k++)
			{
				int x = i+dx[k]; int y = j+dy[k];
				if(isvalid(x, y))
				{
					//cerr<<i<<' '<<j<<' '<<x<<' '<<y<<'\n';
					if(X-1==x&&Y-1==y)
					{
						mcmf.addEdge(outid(i,j),inid(x,y),INF,0);
					}
					else
					{
						mcmf.addEdge(outid(i,j),inid(x,y),INF,0);
					}
				}
			}
			if(i==0||i==n-1||j==0||j==m-1)
			{
				mcmf.addEdge(s, inid(i, j),INF,0);
			}
		}
	}
	ii tmp = mcmf.getMinCostFlow(s, e);
	cout << tmp.fi << '\n';
	mcmf.dfs(s);
	for(int i = 0; i < n; i++)
	{
		for(int j = 0; j < m; j++)
		{
			if((mcmf.me[inid(i,j)]^mcmf.me[outid(i,j)]))
			{
				cout<<'X';
			}
			else
			{
				cout<<'.';
			}
		}
		cout<<'\n';
	}
}