Description
Solution
显然状态永远是阶梯状,设第 \(i\) 行的棋子数为 \(x_i\),则 \(\sum\limits_{i=2}^{n}x_i-x_{i-1}=m\),插板法算出状态数为 \(\binom{n+m}{n}\),直接记搜。
Code
#include <cstdio>
#include <tr1/unordered_map>
const int INF = 0x3f3f3f3f;
int n, m, a[11][11], b[11][11], s[11];
std::tr1::unordered_map<int,int> mp;
int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x;
}
int min(int x, int y) {
return x < y ? x : y;
}
int max(int x, int y) {
return x > y ? x : y;
}
int hash() {
int res = 0;
for (int i = 1; i <= n; ++i) res = res * 11 + m - s[i];
return res;
}
int dfs(int k) {
int now = hash();
if (now == 0) return 0;
if (mp.count(now)) return mp[now];
int res = k ? INF : -INF, tmp;
for (int i = 1; i <= n; ++i)
if (s[i] < m && (i == 1 || s[i-1] > s[i])) {
++s[i], tmp = dfs(k ^ 1);
res = k ? min(res, tmp - b[i][s[i]]) : max(res, tmp + a[i][s[i]]);
--s[i];
}
return (mp[now] = res);
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) a[i][j] = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j) b[i][j] = read();
printf("%d\n", dfs(0));
return 0;
}