import std.stdio;
import std.string;
import std.array;
import std.conv;
import std.algorithm : map, find, min;

void fill(T)(T[][] target, int sy, int sx, int ty, int tx, T[][] v) {
    foreach (i; sy .. ty) {
        foreach (j; sx .. tx) {
            target[i][j] = v[i - sy][j -sx];
        }
    }
}

void fill(T)(T[][] target, int sy, int sx, int ty, int tx, T v) {
    foreach (i; sy .. ty) {
        foreach (j; sx .. tx) {
            target[i][j] = v;
        }
    }
}

int[][] copy(int[][] src, int sy, int sx, int ty, int tx) {
    int[][] backup = new int[][src.length];
    foreach (ref _; backup) _ = new int[src[0].length];
    foreach (i; sy .. ty) {
        foreach (j; sx .. tx) {
            backup[i - sy][j - sx] = src[i][j];
        }
    }
    return backup;
}

void main() {
    int X, Y, n;
    int[] memo;
    int[][] F;
    bool[] used;
    bool[][] mark;
    int count = 0;
    bool exist(int sy, int sx, int ty, int tx, int v) {
        foreach (y; sy .. ty) {
            foreach (x; sx .. tx) {
                if (F[y][x] == v) return true;
            }
        }
        return false;
    }
    bool onlyExist(int sy, int sx, int ty, int tx, int[] vs) {
        foreach (y; sy .. ty) {
            foreach (x; sx .. tx) {
                if (vs.find(F[y][x]).empty) {
                    return false;
                }
            }
        }
        return true;
    }
    int[][] answer;
    void check() { // 答えになっているか
        if (!exist(0, 0, Y, X, 0)) {
            count++;
        }
        fill(answer, 0, 0, Y, X, F);
    }
    void solve(int y, int x) {
        if (y == Y) {
            check();
            return; // 基底
        }
        if (x == X) {
            solve(y + 1, 0);
            return;
        }
        if (mark[y][x]) {
            solve(y, x + 1);
            return;
        }
        const DEBUG = false;
        static if (DEBUG) {
            writeln("solve: ", [y, x]);
            writeln("used: ", used.map!(to!int).array);
            foreach (L; F) {
                writeln(L);
            }
            writeln("mark");
            foreach (m; mark) {
                writeln(m.map!(to!int).array);
            }
        }
        foreach (i; 1 .. n + 1) {
            if (used[i]) continue;
            foreach (dy; 1 .. memo[i] + 1) {
                if (y + dy > Y) continue;
                if (memo[i] % dy != 0) continue;
                int dx = memo[i] / dy;
                if (x + dx > X) continue;
                if ( !( exist(y, x, y + dy, x + dx, i) &&
                        onlyExist(y, x, y + dy, x + dx, [0, i]) ) ) continue;
                fill(mark, y, x, y + dy, x + dx, true);
                int[][] backup = copy(F, y, x, y + dy, x + dx);
                fill(F, y, x, y + dy, x + dx, i);
                used[i] = true;
                solve(y, x);
                fill(mark, y, x, y + dy, x + dx, false);
                F.fill(y, x, y + dy, x + dx, backup);
                delete(backup);
                used[i] = false;
            }
        }
    }
    while (readf("%d %d %d\n", &X, &Y, &n), X || Y || n) {
        memo = new int[n + 1];
        foreach (i; 0 .. n) {
            int index, c; readf("%d %d\n", &index, &c);
            memo[index] = c;
        }
        F = new int[][Y];
        foreach (ref _; F) {
            _ = readln.chomp.split(" ").map!(to!int).array;
        }
        mark = new bool[][Y];
        foreach (ref _; mark) {
            _ = new bool[X];
        }
        used = new bool[n + 1];
        answer = new int[][Y]; foreach (ref _; answer) _ = new int[X];
        count = 0;
        solve(0, 0);
        if (count == 1) {
            foreach (l; answer) {
                l.map!(to!string).join(" ").writeln;
            }
        } else {
            "NA".writeln;
        }
    }
}