[九省联考 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