#include <bits/stdc++.h>
using namespace std;
struct disjoint_set {
  int P[1003];
  disjoint_set() {
    for (int i = 0; i < 1003; i++) P[i] = i;
  }
  int at(int x) {
    if (x == P[x]) return x;
    return P[x] = at(P[x]);
  }
  void join(int x, int y) { P[at(x)] = at(y); }
} Label;
int n, m, k, w, c[1003][1003];
int Parent[1003];
vector<int> b[1003];
vector<string> Table[1003];
void read_map(vector<string> &a) {
  char s[1003];
  a.resize(m);
  for (int i = 0; i < m; i++) {
    scanf("%s", s);
    a[i] = s;
  }
}
int kruskal() {
  vector<pair<int, pair<int, int> > > e;
  for (int i = 0; i < k + 1; i++)
    for (int j = 0; j < k + 1; j++)
      e.push_back(pair<int, pair<int, int> >(c[i][j], pair<int, int>(i, j)));
  sort(e.begin(), e.end());
  int Sum = 0;
  for (int i = 0; i < e.size(); i++) {
    int x = e[i].second.first, y = e[i].second.second;
    if (Label.at(x) == Label.at(y)) continue;
    if (y) b[x].push_back(y);
    if (x) b[y].push_back(x);
    Label.join(x, y);
    Sum += e[i].first;
  }
  return Sum;
}
int cost(int x, int y) {
  int Sum = 0;
  for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++) Sum += Table[x][i][j] != Table[y][i][j];
  if (x == 0 || y == 0) return min(Sum * w, m * n);
  return Sum * w;
}
void visit(int u, int p) {
  if (u != 0) printf("%d %d\n", u, p);
  Parent[u] = p;
  for (int i = 0; int v = b[u][i]; i++)
    if (v != p) visit(v, u);
}
int main() {
  scanf("%d%d%d%d", &m, &n, &k, &w);
  Table[0] = vector<string>(m, string(n, '?'));
  for (int i = 1; i <= k; i++) read_map(Table[i]);
  for (int i = 0; i < k + 1; i++)
    for (int j = 0; j < k + 1; j++) c[i][j] = cost(i, j);
  cout << kruskal() << endl;
  for (int i = 0; i < k + 1; i++) b[i].push_back(0);
  visit(0, 0);
}
