c/c++语言开发共享codechef Table Game(博弈)

题意 题目链接 很难概括。。 Sol (因为比赛还没结束,所以下面讲的可能是“非官方”“正解”) maya这题我前前后后 断断续续的做了一个星期才A掉。CC一场challenge出两道打表题可有点过分了啊。。 首先考虑暴力怎么打,我们把给出的初始行列的01取反,这样$0$的时候对应的是必胜态,$1$ …


题意

题目链接

很难概括。。

sol

(因为比赛还没结束,所以下面讲的可能是“非官方”“正解”)

maya这题我前前后后 断断续续的做了一个星期才a掉。cc一场challenge出两道打表题可有点过分了啊。。

首先考虑暴力怎么打,我们把给出的初始行列的01取反,这样$0$的时候对应的是必胜态,$1$对应的是必败态。

然后按博弈论的定义推,$(i, j)$若是必胜态,那么至少有$(i – 1, j)$是必败态 或者 $(i, j – 1)$是必败态。

然后暴力枚举一遍就行了,复杂度$o(nm)$

接下来的操作就比较神仙了,,打表 或 直接观察式子可得,若第$(i, j)$个点是必败点,那么它所在的对角线往后的点,都是必败点!

这样我们就把状态降到了$2 * m$

那最开始的必败点怎么求呢?

直觉告诉我们 稍加证明不难得到,这种点一定是出现在前两行 或者前两列。

然后就做完了。

暴力推前两行 前两列即可。

保险起见我推了三行三列。

#include<cstdio>  #include<cstring>  #include<vector>  #define ll long long   using namespace std;  const int maxn = 1e5 + 10;  inline ll read() {      char c = getchar(); ll x = 0, f = 1;      while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}      while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();      return x * f;  }  int t;  int a[4][maxn], b[maxn][4], n, m, f[maxn], g[maxn];  char a[maxn], b[maxn];  int main() {   //-    freopen("a.out", "w", stdout);      int t = read();      while(t--) {          scanf("%s", a + 1);          scanf("%s", b + 1);          m = strlen(a + 1);          n = strlen(b + 1);          for(int i = 1; i <= m; i++) a[0][i] = (a[i] == '1' ? 0 : 1);          for(int i = 1; i <= 3; i++) a[i][0] = (b[i] == '1' ? 0 : 1);                    for(int i = 1; i <= 3; i++) b[0][i] = (a[i] == '1' ? 0 : 1);          for(int i = 1; i <= n; i++) b[i][0] = (b[i] == '1' ? 0 : 1);                    memset(f, 0x7f, sizeof(f));          memset(g, 0x7f, sizeof(g));                    for(int i = 1; i <= 3; i++) {              for(int j = 1; j <= m; j++) {                  if(a[i - 1][j] == 1 || a[i][j - 1] == 1) a[i][j] = 0;//能到达必败节点的                   else a[i][j] = 1;                  if(a[i][j] == 1) f[j - i + 1] = min(f[j - i + 1], i);              }          }                    for(int i = 1; i <= n; i++) {              for(int j = 1; j <= 3; j++) {                  if(b[i - 1][j] == 1 || b[i][j - 1] == 1) b[i][j] = 0;                  else b[i][j] = 1;                  if(b[i][j] == 1) g[i - j + 1] = min(g[i - j + 1], j);              }          }          vector<int> ans;          int q = read();          while(q--) {              int x = read(), y = read();              int dy = y - x + 1,                  dx = x - y + 1;              if(dy >= 1) {                  if(x >= f[dy]) ans.push_back(0);                  else ans.push_back(1);               } else {                  if(y >= g[dx]) ans.push_back(0);                  else ans.push_back(1);              }          }          for(int i = 0; i < ans.size(); i++) printf("%d", ans[i]);                  puts("");      }        return 0;  }  /*  2  101  01  6  1 1  1 2  1 3  2 1  2 2  2 3  101  01  6  1 1  1 2  1 3  2 1  2 2  2 3  */

 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/607839.html

(0)
上一篇 2021年5月14日
下一篇 2021年5月14日

精彩推荐