【题目链接】
【思路要点】
- 显然,任意时刻游戏棋盘的轮廓线是单调的。
- 因此,我们可以用一个\(O(N+M)\)位的二进制数描述一个轮廓线。
- 记忆化搜索即可,时间复杂度\(O(M*\binom{N+M}{N})\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 105; const int MAXS = 1 << 21; const int INF = 1e9; template <typename T> void read(T &x) { int f = 1; x = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -f; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; x *= f; } int bit[MAXN], n, m; int val[MAXN][MAXN]; int ans[MAXS], bns[MAXS]; bool vis[MAXS]; int get(int s, bool first) { if (s == (1 << m) - 1) return 0; if (first) { if (vis[s]) return ans[s]; int tans = -INF, x = m, y = 0; for (int i = n + m; i >= 1; i--) { if (bit[i] & s) { if (i != 1 && (bit[i - 1] & s) == 0) tans = max(tans, get(s ^ bit[i] ^ bit[i - 1], false) + val[y + 1][x]); x--; } else y++; } vis[s] = true; return ans[s] = tans; } else { if (vis[s]) return bns[s]; int tans = INF, x = m, y = 0; for (int i = n + m; i >= 1; i--) { if (bit[i] & s) { if (i != 1 && (bit[i - 1] & s) == 0) tans = min(tans, get(s ^ bit[i] ^ bit[i - 1], true)); x--; } else y++; } vis[s] = true; return bns[s] = tans; } } int main() { read(n), read(m); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) read(val[i][j]); int tsum = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { int x; read(x); val[i][j] += x; tsum += x; } for (int i = 1; i <= n + m; i++) bit[i] = 1 << (i - 1); printf("%d\n", get(((1 << m) - 1) << n, 1) - tsum); return 0; }