import sys
from collections import deque

# --------- Utils to map grid <-> graph ----------
def read_input():
    data = sys.stdin.read().strip().splitlines()
    N = int(data[0].strip())
    W = 2*N - 1
    rows = [list(data[i+1].rstrip("\n")) for i in range(N)]
    return N, W, rows

def pyramid_segments(N, W, rows):
    L, R, width = [0]*N, [0]*N, [0]*N
    total_mines = 0
    for r in range(N):
        l = 0
        while l < W and rows[r][l] == '#': l += 1
        rr = W - 1
        while rr >= 0 and rows[r][rr] == '#': rr -= 1
        if l > rr:
            return None
        L[r], R[r] = l, rr
        width[r] = rr - l + 1
        for c in range(l, rr+1):
            if rows[r][c] == 'C':
                total_mines += 1
    return L, R, width, total_mines

# Build graph: give every pyramid cell an id in [0..V-1]
def build_graph(N, W, rows, L, R):
    id_at = [[-1]*W for _ in range(N)]
    cells = []
    mines = []
    vid = 0
    for r in range(N):
        for c in range(L[r], R[r]+1):
            id_at[r][c] = vid
            cells.append((r, c))
            mines.append(1 if rows[r][c] == 'C' else 0)
            vid += 1
    V = vid

    # adjacency with direction tags: 0=up,1=down,2=left,3=right
    adj = [[] for _ in range(V)]
    for v, (r, c) in enumerate(cells):
        # up
        if r-1 >= 0 and L[r-1] <= c <= R[r-1]:
            u = id_at[r-1][c]
            if u != -1: adj[v].append((u, 0))
        # down
        if r+1 < N and L[r+1] <= c <= R[r+1]:
            u = id_at[r+1][c]
            if u != -1: adj[v].append((u, 1))
        # left
        if c-1 >= L[r]:
            u = id_at[r][c-1]
            if u != -1: adj[v].append((u, 2))
        # right
        if c+1 <= R[r]:
            u = id_at[r][c+1]
            if u != -1: adj[v].append((u, 3))
    return V, id_at, cells, mines, adj

# --------- Build a spanning tree (fast) ----------
def build_tree(V, adj, root, order_perm):
    """
    Iterative DFS to build a spanning tree.
    order_perm is a tuple permutation of (0,1,2,3) to reorder neighbor directions.
    Returns parent array and traversal order.
    """
    parent = [-1]*V
    order = []
    st = [root]
    parent[root] = root
    while st:
        v = st.pop()
        order.append(v)
        # small local arrays/few neighbors -> inline reorder by dir
        # collect neighbors grouped by direction
        buckets = [[], [], [], []]
        for (u, d) in adj[v]:
            buckets[d].append(u)
        # push neighbors in reversed stack order respecting permutation
        for d in order_perm[::-1]:
            for u in buckets[d]:
                if parent[u] == -1:
                    parent[u] = v
                    st.append(u)
    return parent, order

# --------- Compute subtree sums and test for a cut ----------
def find_balanced_cut(V, parent, order, mines, target):
    """
    Given a rooted tree (parent, order), compute subtree mine sums and
    check if any non-root node's subtree equals target. If found, return that node.
    """
    sub = [0]*V
    for v in order:
        sub[v] = mines[v]
    # post-order: process in reverse visiting order
    for v in reversed(order):
        p = parent[v]
        if v != p:  # not root
            sub[p] += sub[v]
    # find edge (v-parent[v]) with sub[v] == target
    for v in range(V):
        if v != parent[v] and sub[v] == target:
            return v
    return -1

# --------- Color by tree cut ----------
def color_by_cut(V, parent, cut_node):
    """
    Color subtree of cut_node as 'A', others 'B'.
    Return color array of length V with 'A'/'B'.
    """
    color = ['B']*V
    # mark subtree nodes
    st = [cut_node]
    while st:
        v = st.pop()
        color[v] = 'A'
        # traverse children: any u with parent[u] == v
        # To avoid O(V^2), first build child lists lazily:
        # We can walk all nodes and push those with parent[u]==v by scanning once beforehand,
        # but to keep it fast, we’ll precompute children list once outside. (Small tweak below.)
        # For simplicity here: do a second pass using order — still O(V) since each edge used once.
    return color  # placeholder (we'll compute children faster below)

def build_children(V, parent, order):
    children = [[] for _ in range(V)]
    for v in order:
        p = parent[v]
        if v != p:
            children[p].append(v)
    return children

def mark_subtree_A(children, cut_node, color):
    st = [cut_node]
    while st:
        v = st.pop()
        color[v] = 'A'
        st.extend(children[v])

# --------- Main heuristic driver ----------
def solve():
    N, W, rows = read_input()
    seg = pyramid_segments(N, W, rows)
    if seg is None:
        print("Impossible")
        return
    L, R, width, total_mines = seg
    if total_mines % 2 == 1:
        print("Impossible")
        return
    target = total_mines // 2

    V, id_at, cells, mines, adj = build_graph(N, W, rows, L, R)

    # candidate roots: apex, several along bottom row, some copper cells, a few random-ish
    roots = []
    apex = id_at[0][L[0]]  # top middle
    roots.append(apex)

    # bottom row spread: left/center/right-ish
    bL, bR = L[-1], R[-1]
    bottoms = [bL, (bL+bR)//2, bR]
    for c in bottoms:
        roots.append(id_at[N-1][c])

    # first ~30 copper cells (scan order)
    cnt = 0
    for r in range(N):
        for c in range(L[r], R[r]+1):
            if rows[r][c] == 'C':
                roots.append(id_at[r][c])
                cnt += 1
                if cnt >= 30:
                    break
        if cnt >= 30:
            break

    # clamp unique
    roots = list(dict.fromkeys(roots))

    # neighbor direction permutations to diversify trees
    perms = [
        (0,1,2,3),  # up,down,left,right
        (1,0,2,3),  # down,up,left,right
        (2,3,0,1),  # left,right,up,down
        (3,2,1,0),  # right,left,down,up
        (0,2,1,3),
        (1,3,0,2),
        (3,0,2,1),
        (2,1,3,0),
    ]

    MAX_TRIES = min(64, max(8, 2*len(roots)))
    tried = 0

    for i in range(MAX_TRIES):
        root = roots[i % len(roots)]
        order_perm = perms[i % len(perms)]
        parent, order = build_tree(V, adj, root, order_perm)
        if -1 in parent:
            # graph should be connected; but just in case, skip
            continue
        cut_node = find_balanced_cut(V, parent, order, mines, target)
        if cut_node != -1:
            # Color A = subtree(cut_node), B = rest
            children = build_children(V, parent, order)
            color = ['B']*V
            mark_subtree_A(children, cut_node, color)

            # Emit output
            out = []
            for r in range(N):
                line = rows[r][:]
                for c in range(L[r], R[r]+1):
                    v = id_at[r][c]
                    line[c] = 'A' if color[v] == 'A' else 'B'
                out.append(''.join(line))
            #print(i)
            print('\n'.join(out))
            return
        tried += 1

    # If we reach here, we didn't find an exact half-subtree cut
    print("Impossible")


if __name__ == "__main__":
    solve()
