[九省联考 2018]一双木棋chess

Posted NaVi_Awson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[九省联考 2018]一双木棋chess相关的知识,希望对你有一定的参考价值。

Description

题库链接

给出一个 \(n\times m\) 的棋盘,棋盘的每个格子有两个权值 \(A,B\) 。 Alice 和 Bob 轮流操作在棋盘上放棋子,一个格子能放棋子的前提条件是这个格子的左侧和上侧均放了棋子。对于 Alice 放棋子的格子,能获得该格子的 \(A\) 的权值;对于 Bob 放棋子的格子,能获得该格子的 \(B\) 的权值。 Alice 想最大化得分差, Bob 想最小化得分差,求最后得分差。

\(1\leq n,m\leq 10\)

Solution

比较简单啊,状压轮廓线记搜就好了。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 10+5;
const int SIZE = (1<<20)+5;

int n, m, a[N][N], b[N][N], bin[N<<1];
int f[SIZE], inf;

int dfs(int S, int who) {
    if (f[S] != -inf) return f[S];
    int ans = who ? -inf : inf;
    for (int i = 0, loc = 0; i < n+m; i++) {
        if (S&bin[i]) ++loc;
        if (S&bin[i+1] && !(S&bin[i])) {
            int t = dfs(S-bin[i+1]+bin[i], who^1);
            if (who == 1) ans = max(ans, t+a[n-i+loc][loc+1]);
            else ans = min(ans, t-b[n-i+loc][loc+1]);
        }
    }
    if (abs(ans) == inf) ans = 0; f[S] = ans;
    return f[S];
}
void work() {
    memset(f, 128, sizeof(f)); inf = -f[0];
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]);
    for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &b[i][j]);
    bin[0] = 1; for (int i = 1; i <= 21; i++) bin[i] = (bin[i-1]<<1);
    int states = 0;
    for (int i = 1; i <= m; i++) states |= bin[n-1+i];
    printf("%d\n", dfs(states, 1));
}
int main() {work(); return 0; }

以上是关于[九省联考 2018]一双木棋chess的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P4363 [九省联考2018]一双木棋chess

P4363 [九省联考2018]一双木棋chess(对抗搜索+记忆化搜索)

BZOJ5248九省联考2018一双木棋(搜索,哈希)

[BZOJ5248][九省联考2018]双木棋chess

P4363 [九省联考2018]一双木棋

[2018九省联考]一双木棋