[SDOI 2018] 一雙木棋 chess
阿新 • • 發佈:2018-12-05
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; }