## 1. Abridged problem statement

You are given an `N x M` chessboard (`N, M <= 300`) with:

- empty cells `.`,
- walls/sculptures `#` that block movement/attacks and cannot be captured,
- stationary colorless chess pieces:
  - `P` pawn,
  - `R` rook,
  - `K` knight,
  - `B` bishop,
  - `Q` queen,
  - `M` king,
- your starting cell `@`.

Before moving, you choose your own piece type: pawn, rook, knight, bishop, or king — never queen.

You move according to chess rules. Capturing a stationary piece removes it and gives a piece-specific bonus. After every move, if your current cell is attacked by any remaining stationary piece, training ends and you pay a penalty. You may also quit before any move with no penalty.

Pawns: colorless pawns attack toward decreasing row numbers; your pawn moves in the opposite direction.

Maximize final score.

---

## 2. Detailed editorial

### Key observations

We only need to consider choosing one of:

```text
rook, knight, bishop, king
```

The provided solution ignores choosing a pawn. A pawn can only move monotonically downward and is dominated by a king: every square a pawn could safely enter or capture can also be entered by a king, while the king has more options. Therefore pawn is never strictly better.

---

### Attacked-cell counts

For every cell, compute:

```text
base_count[cell] = number of stationary pieces attacking this cell
```

A cell is safe iff:

```text
base_count[cell] == 0
```

The stationary pieces never move, but captured pieces disappear, so attack counts can decrease.

Sliding attacks from rooks, bishops, and queens are computed efficiently using directional sweeps.

For example, for a rook-like direction, while sweeping left-to-right, we remember whether the nearest blocker behind the current cell is a rook or queen. If yes, the current cell is attacked from that direction.

Non-sliding attacks from pawns, knights, and kings are stamped directly.

---

### Important lemma

Suppose we capture a piece while standing safely on its square.

That square has attack count zero. Therefore, no sliding enemy piece attacks that square. Hence the captured piece cannot be the first blocker in front of a rook/bishop/queen that would start attacking farther squares after the capture.

So capturing a safe piece does **not open new sliding attacks**.

It only removes the attacks made by the captured piece itself.

Therefore during safe play:

```text
attack counts only decrease
```

This is the central trick.

---

### Closure of reachable safe area

For a chosen moving type, define a process:

1. Start from one or more safe seed cells.
2. Flood all safe empty cells reachable by legal moves.
3. If a reachable cell can move to a safe capturable piece, capture it.
4. Capturing removes its attacks, possibly making more cells safe.
5. Newly safe reachable cells or pieces are added.
6. Repeat until nothing changes.

This computes all free captures possible without ever landing on an attacked cell.

At the end, we may optionally make one final risky capture onto an attacked piece:

```text
bonus(piece) - penalty
```

If this value is positive, take it; otherwise quit safely.

---

### Handling the starting square

If `@` is initially safe, it is just a normal seed cell.

If `@` is attacked, we are allowed to stand there only before making the first move. After the first move, we cannot treat it as part of the safe connected region unless it later becomes safe.

So for each possible first move:

- If it lands on a safe empty cell, run closure from that safe component.
- If it captures a safe piece, remove that piece and run closure from its square.
- If it captures an attacked piece, that is immediately a losing final move worth:

```text
bonus - penalty
```

Take the maximum over all first moves and all piece types.

---

### Complexity

Let `V = N * M`.

Computing initial attack counts is roughly:

```text
O(V)
```

Each closure may scan legal moves many times; in the worst case the provided solution is around:

```text
O(V * (N + M))
```

for sliding pieces.

This is acceptable in the intended C++ setting.

---

## 3. C++ Solution

```cpp
#include <bits/stdc++.h>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }

    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }

    return out;
};

const int64_t NEG = LLONG_MIN / 4;

int n, m;
int start_r, start_c;
int bonus_pawn, bonus_rook, bonus_knight, bonus_bishop, bonus_queen, bonus_king;
int penalty;
vector<string> grid;
vector<int> base_count;

const int knight_d[8][2] = {{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
                            {1, -2},  {1, 2},  {2, -1},  {2, 1}};

const int king_d[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
                          {0, 1},   {1, -1}, {1, 0},  {1, 1}};

const int rook_d[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
const int bishop_d[4][2] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};

void read() {
    cin >> n >> m;
    cin >> bonus_pawn >> bonus_rook >> bonus_knight >> bonus_bishop >>
        bonus_queen >> bonus_king >> penalty;
    grid.assign(n, string());
    for(int i = 0; i < n; i++) {
        cin >> grid[i];
    }

    for(int r = 0; r < n; r++) {
        for(int c = 0; c < m; c++) {
            if(grid[r][c] == '@') {
                start_r = r;
                start_c = c;
            }
        }
    }
}

bool in_board(int r, int c) { return r >= 0 && r < n && c >= 0 && c < m; }

bool is_piece(char ch) {
    return ch == 'P' || ch == 'R' || ch == 'K' || ch == 'B' || ch == 'Q' ||
           ch == 'M';
}

bool blocks_ray(char ch) { return ch != '.' && ch != '@'; }

int capture_bonus(char ch) {
    switch(ch) {
        case 'P':
            return bonus_pawn;
        case 'R':
            return bonus_rook;
        case 'K':
            return bonus_knight;
        case 'B':
            return bonus_bishop;
        case 'Q':
            return bonus_queen;
        case 'M':
            return bonus_king;
    }

    return 0;
}

template<typename F>
void for_moves(char type, int r, int c, F fn) {
    bool slide = type == 'R' || type == 'B';
    const int(*dirs)[2] = type == 'K'   ? knight_d
                          : type == 'M' ? king_d
                          : type == 'R' ? rook_d
                                        : bishop_d;
    int k = slide ? 4 : 8;
    for(int i = 0; i < k; i++) {
        int nr = r + dirs[i][0], nc = c + dirs[i][1];
        if(!slide) {
            if(in_board(nr, nc)) {
                fn(nr, nc);
            }

            continue;
        }

        while(in_board(nr, nc) && !fn(nr, nc)) {
            nr += dirs[i][0];
            nc += dirs[i][1];
        }
    }
}

template<typename F>
void for_footprint(const vector<string>& g, char t, int pr, int pc, F fn) {
    auto ray = [&](int dr, int dc) {
        int r = pr + dr, c = pc + dc;
        while(in_board(r, c)) {
            fn(r * m + c);
            if(blocks_ray(g[r][c])) {
                break;
            }

            r += dr;
            c += dc;
        }
    };
    auto spot = [&](int dr, int dc) {
        int r = pr + dr, c = pc + dc;
        if(in_board(r, c)) {
            fn(r * m + c);
        }
    };

    if(t == 'R' || t == 'Q') {
        for(auto& d: rook_d) {
            ray(d[0], d[1]);
        }
    }

    if(t == 'B' || t == 'Q') {
        for(auto& d: bishop_d) {
            ray(d[0], d[1]);
        }
    }

    if(t == 'K') {
        for(auto& d: knight_d) {
            spot(d[0], d[1]);
        }
    } else if(t == 'M') {
        for(auto& d: king_d) {
            spot(d[0], d[1]);
        }
    } else if(t == 'P') {
        spot(-1, -1);
        spot(-1, 1);
    }
}

void compute_base_count() {
    base_count.assign(n * m, 0);
    vector<int> active(n * m, 0);

    auto sweep = [&](int dr, int dc, bool diagonal) {
        int r0 = dr >= 0 ? 0 : n - 1, r1 = dr >= 0 ? n : -1,
            rs = dr >= 0 ? 1 : -1;
        int c0 = dc >= 0 ? 0 : m - 1, c1 = dc >= 0 ? m : -1,
            cs = dc >= 0 ? 1 : -1;
        for(int r = r0; r != r1; r += rs) {
            for(int c = c0; c != c1; c += cs) {
                int pr = r - dr, pc = c - dc;
                int inc;
                if(!in_board(pr, pc)) {
                    inc = 0;
                } else if(blocks_ray(grid[pr][pc])) {
                    char p = grid[pr][pc];
                    inc = diagonal ? (p == 'B' || p == 'Q')
                                   : (p == 'R' || p == 'Q');
                } else {
                    inc = active[pr * m + pc];
                }

                active[r * m + c] = inc;
                if(inc) {
                    base_count[r * m + c]++;
                }
            }
        }
    };

    sweep(0, 1, false);
    sweep(0, -1, false);
    sweep(1, 0, false);
    sweep(-1, 0, false);
    sweep(1, 1, true);
    sweep(1, -1, true);
    sweep(-1, 1, true);
    sweep(-1, -1, true);

    for(int r = 0; r < n; r++) {
        for(int c = 0; c < m; c++) {
            char ch = grid[r][c];
            if(is_piece(ch) && ch != 'R' && ch != 'B' && ch != 'Q') {
                for_footprint(grid, ch, r, c, [&](int idx) {
                    base_count[idx]++;
                });
            }
        }
    }
}

void uncount_piece(vector<string>& g, vector<int>& cnt, int pr, int pc) {
    char t = g[pr][pc];
    for_footprint(g, t, pr, pc, [&](int idx) { cnt[idx]--; });
    g[pr][pc] = '.';
}

pair<int64_t, int64_t> closure(
    char type, vector<string> g, vector<int> cnt,
    const vector<pair<int, int>>& seeds
) {
    int64_t free_sum = 0;
    vector<char> reach(n * m, 0), sched(n * m, 0), risky_mark(n * m, 0);
    vector<int> work, capq, risky_cells;

    auto can_pull = [&](int x) {
        bool found = false;
        for_moves(type, x / m, x % m, [&](int nr, int nc) {
            if(reach[nr * m + nc]) {
                found = true;
                return true;
            }

            return g[nr][nc] == '#' || is_piece(g[nr][nc]);
        });
        return found;
    };

    auto on_zero = [&](int x) {
        if(g[x / m][x % m] == '#' || reach[x]) {
            return;
        }

        if(is_piece(g[x / m][x % m])) {
            if(!sched[x] && can_pull(x)) {
                sched[x] = 1;
                capq.push_back(x);
            }
        } else if(can_pull(x)) {
            reach[x] = 1;
            work.push_back(x);
        }
    };

    auto take = [&](int pr, int pc) {
        char t = g[pr][pc];
        int idx = pr * m + pc;
        free_sum += capture_bonus(t);
        reach[idx] = 1;
        g[pr][pc] = '.';
        work.push_back(idx);
        for_footprint(g, t, pr, pc, [&](int x) {
            if(--cnt[x] == 0) {
                on_zero(x);
            }
        });
    };

    auto scan = [&](int u) {
        for_moves(type, u / m, u % m, [&](int nr, int nc) {
            int idx = nr * m + nc;
            char ch = g[nr][nc];
            if(ch == '#') {
                return true;
            }

            if(is_piece(ch)) {
                if(cnt[idx] == 0) {
                    if(!sched[idx]) {
                        sched[idx] = 1;
                        capq.push_back(idx);
                    }
                } else if(!risky_mark[idx]) {
                    risky_mark[idx] = 1;
                    risky_cells.push_back(idx);
                }

                return true;
            }

            if(cnt[idx] == 0) {
                if(!reach[idx]) {
                    reach[idx] = 1;
                    work.push_back(idx);
                }

                return true;
            }

            return false;
        });
    };

    for(auto [sr, sc]: seeds) {
        if(!reach[sr * m + sc]) {
            reach[sr * m + sc] = 1;
            work.push_back(sr * m + sc);
        }
    }

    while(!work.empty() || !capq.empty()) {
        while(!work.empty()) {
            int u = work.back();
            work.pop_back();
            scan(u);
        }

        while(!capq.empty()) {
            int p = capq.back();
            capq.pop_back();
            take(p / m, p % m);
        }
    }

    int64_t best_risky = NEG;
    for(int idx: risky_cells) {
        char ch = g[idx / m][idx % m];
        if(is_piece(ch)) {
            best_risky = max(best_risky, (int64_t)capture_bonus(ch) - penalty);
        }
    }

    return {free_sum, best_risky};
}

int64_t closure_value(
    char type, const vector<string>& g, const vector<int>& cnt,
    const vector<pair<int, int>>& seeds
) {
    auto [f, rk] = closure(type, g, cnt, seeds);
    return f + (rk > NEG ? max((int64_t)0, rk) : 0);
}

void flood_component(char type, int sr, int sc, vector<char>& seen) {
    vector<pair<int, int>> st = {{sr, sc}};
    seen[sr * m + sc] = 1;
    while(!st.empty()) {
        auto [r, c] = st.back();
        st.pop_back();
        for_moves(type, r, c, [&](int nr, int nc) {
            int idx = nr * m + nc;
            char ch = grid[nr][nc];
            if(ch == '#' || is_piece(ch)) {
                return true;
            }

            if(base_count[idx] == 0) {
                if(!seen[idx]) {
                    seen[idx] = 1;
                    st.push_back({nr, nc});
                }

                return true;
            }

            return false;
        });
    }
}

int64_t eval_reversible(char type) {
    if(base_count[start_r * m + start_c] == 0) {
        return closure_value(type, grid, base_count, {{start_r, start_c}});
    }

    int64_t best = 0;
    vector<pair<int, int>> empties, capfirst;

    for_moves(type, start_r, start_c, [&](int nr, int nc) {
        int idx = nr * m + nc;
        char ch = grid[nr][nc];
        if(ch == '#') {
            return true;
        }

        if(is_piece(ch)) {
            if(base_count[idx] == 0) {
                capfirst.push_back({nr, nc});
            } else {
                best = max(best, (int64_t)capture_bonus(ch) - penalty);
            }

            return true;
        }

        if(base_count[idx] == 0) {
            empties.push_back({nr, nc});
        }

        return false;
    });

    vector<char> seen(n * m, 0);
    for(auto [r, c]: empties) {
        if(!seen[r * m + c]) {
            flood_component(type, r, c, seen);
            best = max(best, closure_value(type, grid, base_count, {{r, c}}));
        }
    }

    for(auto [pr, pc]: capfirst) {
        vector<string> g2 = grid;
        vector<int> cnt2 = base_count;
        int b = capture_bonus(grid[pr][pc]);
        uncount_piece(g2, cnt2, pr, pc);
        auto [f, rk] = closure(type, g2, cnt2, {{pr, pc}});
        best = max(best, b + f + (rk > NEG ? max((int64_t)0, rk) : 0));
    }

    return best;
}

void solve() {
    // Rules. The board has empty cells, '#' sculptures (immovable walls that
    // block and cannot be captured), colorless pieces (pawn/rook/knight/bishop/
    // queen/king, which never move), and our start '@'. Before starting we pick
    // one piece type - any but a queen - and move it by the usual chess rules.
    // Capturing a colorless piece deletes it from the board and adds its bonus.
    // If after a move our cell is attacked by any surviving colorless piece the
    // training ends and we pay `penalty`; otherwise we may keep going, and we
    // may leave for free at any time. The colorless pawns face the decreasing
    // row direction, so they attack diagonally upward while our own pawn would
    // move downward. We want the largest reachable score.
    //
    // So a run is: collect a set of "free" captures while every landing cell is
    // safe (unattacked), then optionally make one last move onto an attacked
    // cell that captures a piece, worth bonus - penalty, after which the run
    // ends. The hard part is that capturing removes a piece, which removes its
    // attacks and so changes which cells are safe as we go.
    //
    // We only evaluate the reversible pieces (rook, knight, bishop, king). The
    // pawn is left out: it walks a single strictly-downward path and can never
    // collect more than a king touring the same cells, so it is never the lone
    // best choice.
    //
    // Let base_count[cell] be how many colorless pieces attack it. We find it
    // once: eight directional line sweeps handle the sliders (each sweep
    // carries along a line whether the nearest blocker behind the current cell
    // is a matching rook/bishop/queen, so the cell just past such a blocker is
    // attacked), and the fixed footprints of the knights, kings and pawns are
    // stamped directly. A cell is safe exactly when its count is zero.
    //
    // Key lemma: a piece we can safely stand on has count zero, so it is not
    // the first blocker on any slider's ray - otherwise that slider would
    // attack it. Hence capturing a safe piece never lets a slider see further
    // (opens no new ray); it only deletes that piece's own attacks. Counts
    // therefore only shrink during free captures, safe cells stay safe, and we
    // can keep counts exact by decrementing along just the captured piece's
    // footprint, with no resweep - that is what makes the whole thing cheap.
    //
    // closure() does the work for one starting region. A reversible token can
    // roam any connected region of safe cells and always backtrack, so we flood
    // the safe cells from the seeds. Whenever a reached cell is one move from a
    // safe colorless piece we capture it: bank its bonus, mark its now-empty
    // cell reached, and decrement its footprint. A decrement that drops some
    // cell's count to zero makes that cell newly safe; if it is now adjacent to
    // the reached region we pull it in - an empty cell rejoins the flood, a
    // piece becomes capturable - and this cascades until nothing changes. A
    // piece that stays reachable only onto an attacked cell is remembered as a
    // candidate for the single risky last move worth bonus - penalty.
    //
    // The start needs care. If '@' is safe it is an ordinary region cell and
    // one closure seeded there is enough. If '@' is attacked we can stand on it
    // only at move zero - once we leave we can never come back, so different
    // first moves may strand us in different, disconnected safe regions. We
    // therefore try each first move out of '@' and keep the best: moves onto
    // empty safe cells are deduplicated by safe component (one closure per
    // component), a move that captures a safe piece runs a closure with that
    // piece pre-removed, and a move onto an attacked piece is itself a risky
    // final worth its bonus minus penalty.
    //
    // The answer is the best of the four piece types, and at least zero since
    // we may always leave at once. Each closure is O(n*m*(n+m)) in the worst
    // case.

    compute_base_count();

    int64_t ans = 0;
    for(char type: {'R', 'K', 'B', 'M'}) {
        ans = max(ans, eval_reversible(type));
    }

    cout << ans << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        solve();
    }

    return 0;
}
```

---

## 4. Python solution with detailed comments

```python
import sys

# Very negative value used when no risky move exists.
NEG = -(10 ** 30)

# Directions for chess pieces.
KNIGHT_D = [(-2, -1), (-2, 1), (-1, -2), (-1, 2),
            (1, -2), (1, 2), (2, -1), (2, 1)]

KING_D = [(-1, -1), (-1, 0), (-1, 1),
          (0, -1),           (0, 1),
          (1, -1),  (1, 0),  (1, 1)]

ROOK_D = [(-1, 0), (1, 0), (0, -1), (0, 1)]
BISHOP_D = [(-1, -1), (-1, 1), (1, -1), (1, 1)]


def solve():
    data = sys.stdin.read().split()
    it = iter(data)

    n = int(next(it))
    m = int(next(it))

    bonus_pawn = int(next(it))
    bonus_rook = int(next(it))
    bonus_knight = int(next(it))
    bonus_bishop = int(next(it))
    bonus_queen = int(next(it))
    bonus_king = int(next(it))
    penalty = int(next(it))

    grid = [list(next(it)) for _ in range(n)]

    start_r = start_c = -1

    for r in range(n):
        for c in range(m):
            if grid[r][c] == '@':
                start_r, start_c = r, c

    def in_board(r, c):
        """Return True if cell is inside the board."""
        return 0 <= r < n and 0 <= c < m

    def is_piece(ch):
        """Return True if ch is a capturable stationary chess piece."""
        return ch in "PRKBQM"

    def blocks_ray(ch):
        """
        Return True if ch blocks a sliding attack.

        Walls and pieces block.
        Empty cells and '@' do not block.
        """
        return ch != '.' and ch != '@'

    def capture_bonus(ch):
        """Return score bonus for capturing piece ch."""
        if ch == 'P':
            return bonus_pawn
        if ch == 'R':
            return bonus_rook
        if ch == 'K':
            return bonus_knight
        if ch == 'B':
            return bonus_bishop
        if ch == 'Q':
            return bonus_queen
        if ch == 'M':
            return bonus_king
        return 0

    def for_moves(piece_type, r, c, fn):
        """
        Iterate over legal moves of our selected piece.

        fn(nr, nc) is called for each candidate cell.
        For sliding pieces, if fn returns True, the ray stops.
        """
        if piece_type == 'K':
            dirs = KNIGHT_D
            slide = False
        elif piece_type == 'M':
            dirs = KING_D
            slide = False
        elif piece_type == 'R':
            dirs = ROOK_D
            slide = True
        else:
            dirs = BISHOP_D
            slide = True

        if not slide:
            for dr, dc in dirs:
                nr = r + dr
                nc = c + dc

                if in_board(nr, nc):
                    fn(nr, nc)
        else:
            for dr, dc in dirs:
                nr = r + dr
                nc = c + dc

                while in_board(nr, nc):
                    stop = fn(nr, nc)

                    if stop:
                        break

                    nr += dr
                    nc += dc

    def for_footprint(g, t, pr, pc, fn):
        """
        Iterate over cells attacked by stationary piece t at (pr, pc).
        """

        def ray(dr, dc):
            r = pr + dr
            c = pc + dc

            while in_board(r, c):
                fn(r * m + c)

                if blocks_ray(g[r][c]):
                    break

                r += dr
                c += dc

        def spot(dr, dc):
            r = pr + dr
            c = pc + dc

            if in_board(r, c):
                fn(r * m + c)

        if t == 'R' or t == 'Q':
            for dr, dc in ROOK_D:
                ray(dr, dc)

        if t == 'B' or t == 'Q':
            for dr, dc in BISHOP_D:
                ray(dr, dc)

        if t == 'K':
            for dr, dc in KNIGHT_D:
                spot(dr, dc)

        elif t == 'M':
            for dr, dc in KING_D:
                spot(dr, dc)

        elif t == 'P':
            # Colorless pawns attack toward decreasing row index.
            spot(-1, -1)
            spot(-1, 1)

    def compute_base_count():
        """
        Compute initial number of attacks on each cell.
        """
        cnt = [0] * (n * m)
        active = [0] * (n * m)

        def sweep(dr, dc, diagonal):
            """
            Sweep in one direction and count slider attacks.
            """
            r_range = range(n) if dr >= 0 else range(n - 1, -1, -1)
            c_range = range(m) if dc >= 0 else range(m - 1, -1, -1)

            for r in r_range:
                for c in c_range:
                    pr = r - dr
                    pc = c - dc

                    if not in_board(pr, pc):
                        inc = 0
                    elif blocks_ray(grid[pr][pc]):
                        p = grid[pr][pc]

                        if diagonal:
                            inc = 1 if p == 'B' or p == 'Q' else 0
                        else:
                            inc = 1 if p == 'R' or p == 'Q' else 0
                    else:
                        inc = active[pr * m + pc]

                    active[r * m + c] = inc

                    if inc:
                        cnt[r * m + c] += 1

        # Rook-like directions.
        sweep(0, 1, False)
        sweep(0, -1, False)
        sweep(1, 0, False)
        sweep(-1, 0, False)

        # Bishop-like directions.
        sweep(1, 1, True)
        sweep(1, -1, True)
        sweep(-1, 1, True)
        sweep(-1, -1, True)

        # Stamp pawn, knight, and king attacks directly.
        for r in range(n):
            for c in range(m):
                ch = grid[r][c]

                if is_piece(ch) and ch not in "RBQ":
                    for_footprint(grid, ch, r, c,
                                  lambda idx: cnt.__setitem__(idx, cnt[idx] + 1))

        return cnt

    base_count = compute_base_count()

    def uncount_piece(g, cnt, pr, pc):
        """
        Remove piece at (pr, pc) and subtract its attacks.
        """
        t = g[pr][pc]

        def dec(idx):
            cnt[idx] -= 1

        for_footprint(g, t, pr, pc, dec)

        g[pr][pc] = '.'

    def closure(piece_type, given_g, given_cnt, seeds):
        """
        Compute all free captures from safe seed cells.

        Returns:
            free_sum: total free capture score
            best_risky: best optional final risky capture value
        """
        g = [row[:] for row in given_g]
        cnt = given_cnt[:]

        free_sum = 0

        reach = [0] * (n * m)
        sched = [0] * (n * m)
        risky_mark = [0] * (n * m)

        work = []
        capq = []
        risky_cells = []

        def can_pull(x):
            """
            Return True if x can reach any already reached safe cell.
            """
            xr = x // m
            xc = x % m
            found = False

            def cb(nr, nc):
                nonlocal found

                idx = nr * m + nc

                if reach[idx]:
                    found = True
                    return True

                return g[nr][nc] == '#' or is_piece(g[nr][nc])

            for_moves(piece_type, xr, xc, cb)

            return found

        def on_zero(x):
            """
            Called when attack count of cell x becomes zero.
            """
            r = x // m
            c = x % m

            if g[r][c] == '#' or reach[x]:
                return

            if is_piece(g[r][c]):
                if not sched[x] and can_pull(x):
                    sched[x] = 1
                    capq.append(x)
            else:
                if can_pull(x):
                    reach[x] = 1
                    work.append(x)

        def take(pr, pc):
            """
            Safely capture piece at (pr, pc).
            """
            nonlocal free_sum

            t = g[pr][pc]
            idx = pr * m + pc

            free_sum += capture_bonus(t)

            reach[idx] = 1
            g[pr][pc] = '.'
            work.append(idx)

            def dec(x):
                cnt[x] -= 1

                if cnt[x] == 0:
                    on_zero(x)

            for_footprint(g, t, pr, pc, dec)

        def scan(u):
            """
            Scan all moves from reached cell u.
            """
            ur = u // m
            uc = u % m

            def cb(nr, nc):
                idx = nr * m + nc
                ch = g[nr][nc]

                if ch == '#':
                    return True

                if is_piece(ch):
                    if cnt[idx] == 0:
                        if not sched[idx]:
                            sched[idx] = 1
                            capq.append(idx)
                    else:
                        if not risky_mark[idx]:
                            risky_mark[idx] = 1
                            risky_cells.append(idx)

                    return True

                if cnt[idx] == 0:
                    if not reach[idx]:
                        reach[idx] = 1
                        work.append(idx)

                    return True

                # Attacked empty square cannot be landed on,
                # but a rook/bishop may slide through it.
                return False

            for_moves(piece_type, ur, uc, cb)

        # Insert initial seeds.
        for sr, sc in seeds:
            idx = sr * m + sc

            if not reach[idx]:
                reach[idx] = 1
                work.append(idx)

        # Process until no new reachable cell or capture remains.
        while work or capq:
            while work:
                u = work.pop()
                scan(u)

            while capq:
                p = capq.pop()
                take(p // m, p % m)

        best_risky = NEG

        for idx in risky_cells:
            r = idx // m
            c = idx % m
            ch = g[r][c]

            if is_piece(ch):
                best_risky = max(best_risky, capture_bonus(ch) - penalty)

        return free_sum, best_risky

    def closure_value(piece_type, g, cnt, seeds):
        """
        Free closure value plus optional profitable risky capture.
        """
        free_score, risky = closure(piece_type, g, cnt, seeds)

        if risky > NEG:
            return free_score + max(0, risky)

        return free_score

    def flood_component(piece_type, sr, sc, seen):
        """
        Flood a connected component of currently safe empty cells.
        Used to avoid running closure multiple times for equivalent first moves.
        """
        stack = [(sr, sc)]
        seen[sr * m + sc] = 1

        while stack:
            r, c = stack.pop()

            def cb(nr, nc):
                idx = nr * m + nc
                ch = grid[nr][nc]

                if ch == '#' or is_piece(ch):
                    return True

                if base_count[idx] == 0:
                    if not seen[idx]:
                        seen[idx] = 1
                        stack.append((nr, nc))

                    return True

                return False

            for_moves(piece_type, r, c, cb)

    def eval_reversible(piece_type):
        """
        Evaluate best score if we choose piece_type.
        """
        start_idx = start_r * m + start_c

        # If start is safe, one closure is enough.
        if base_count[start_idx] == 0:
            return closure_value(piece_type, grid, base_count, [(start_r, start_c)])

        best = 0

        empties = []
        capfirst = []

        # Otherwise enumerate possible first moves from attacked start.
        def first_cb(nr, nc):
            nonlocal best

            idx = nr * m + nc
            ch = grid[nr][nc]

            if ch == '#':
                return True

            if is_piece(ch):
                if base_count[idx] == 0:
                    capfirst.append((nr, nc))
                else:
                    best = max(best, capture_bonus(ch) - penalty)

                return True

            if base_count[idx] == 0:
                empties.append((nr, nc))

            return False

        for_moves(piece_type, start_r, start_c, first_cb)

        # Try safe empty first moves, one per component.
        seen = [0] * (n * m)

        for r, c in empties:
            idx = r * m + c

            if not seen[idx]:
                flood_component(piece_type, r, c, seen)
                best = max(best, closure_value(piece_type, grid, base_count, [(r, c)]))

        # Try first move capturing a safe piece.
        for pr, pc in capfirst:
            g2 = [row[:] for row in grid]
            cnt2 = base_count[:]

            first_bonus = capture_bonus(grid[pr][pc])

            uncount_piece(g2, cnt2, pr, pc)

            free_score, risky = closure(piece_type, g2, cnt2, [(pr, pc)])

            value = first_bonus + free_score

            if risky > NEG:
                value += max(0, risky)

            best = max(best, value)

        return best

    answer = 0

    # Queen is forbidden; pawn is dominated by king.
    for piece_type in ['R', 'K', 'B', 'M']:
        answer = max(answer, eval_reversible(piece_type))

    print(answer)


if __name__ == "__main__":
    solve()
```

---

## 5. Compressed editorial

Compute how many stationary pieces attack each board cell. A cell is safe iff this count is zero.

Sliding attacks from rooks, bishops, and queens are counted with eight directional sweeps. Pawn, knight, and king attacks are added directly.

The main lemma is: if a piece is captured safely, then its square was not attacked, so removing it cannot open a new sliding attack through that square. Therefore safe captures only decrease attack counts by removing the captured piece’s own attack footprint.

For each possible chosen piece among rook, knight, bishop, and king, compute the closure of all safe cells and safe captures reachable from a starting seed. Whenever a captured piece is removed, decrement counts on its attacked cells; cells whose count becomes zero may join the reachable region or become capturable. At the end, optionally take one final attacked capture worth `bonus - penalty`.

If the start cell is safe, run one closure from it. If it is attacked, enumerate possible first moves separately: safe empty landings, safe first captures, and immediate risky captures.

The answer is the maximum over the four considered piece types, at least zero because quitting immediately is always allowed.