2023NOIP A层联测17 游戏

题目大意

有一个 n × m n\times m n×m的网格图,开始时有三种格子,分别为障碍,棋子和空格。

A A A和小 B B B在这个网格图上玩游戏,双方轮流行动,小 A A A先行动。每次行动中,当前玩家选择一枚棋子移动,设棋子所在的格子为 ( r , c ) (r,c) (r,c),则移动规则如下:

  • 可将格子移到 ( r + 1 , c ) (r+1,c) (r+1,c)(如果 r + 1 ≤ n r+1\leq n r+1n)、 ( r , c − 1 ) (r,c-1) (r,c1)(如果 c > 1 c>1 c>1)、 ( r , c + 1 ) (r,c+1) (r,c+1)(如果 c < m c<m c<m)。特殊地,可以从 ( r , 1 ) (r,1) (r,1)移到 ( r , m ) (r,m) (r,m),也可以从 ( r , m ) (r,m) (r,m)移到 ( r , 1 ) (r,1) (r,1),也就是可以将每一行看作一个环。
  • 棋子不能被移动到包含障碍的格子
  • 一个格子可以包含多个棋子
  • 棋子不能被移动到它曾经到过的格子(所有棋子各不相同,也就是到过的格子是对每个棋子分别记录的)

无法行动的玩家算负。

求在双方都采用最优策略的情况下,最终谁会获胜。

T T T组数据。

1 ≤ n , m ≤ 1000 , 1 ≤ ∑ n , ∑ m ≤ 4000 1\leq n,m\leq 1000,1\leq \sum n,\sum m\leq 4000 1n,m1000,1n,m4000

时间限制 2000 m s 2000ms 2000ms,空间限制 512 M B 512MB 512MB


题解

由于每个格子上可以有多个棋子,且每个棋子走过的路径单独记录,所以每个棋子是独立的。因此,我们可以先计算出每个位置有棋子时的 S G SG SG值,最后再将其异或在起来,即可得到总游戏的 S G SG SG值。

我们考虑 D P DP DP,设 s g [ x ] [ y ] sg[x][y] sg[x][y]表示当前棋子一开始在 ( x , y ) (x,y) (x,y)时的 S G SG SG值,然后从下往上处理。我们分两种情况考虑。

当前行有至少一个包含障碍的格子

在这种情况下,每行都被障碍分成若干段。那么,对于走到这一行的棋子,它的状态只会有三种:

  • 刚从上面走下来,此时可以往左右两边走
  • 从右边走过来,只能往左边走
  • 从左边走过来,只能往右边走

假设当前行为第 t t t行,设 f [ 0 / 1 ] [ i ] f[0/1][i] f[0/1][i]表示当前是从左边或右边走过来,走到当前行的位置 i i i时的 S G SG SG值。我们分别处理从左往右走的 f f f值和从右往左走的 f f f值,对于每个位置 i i i,我们用 s g [ t + 1 ] [ i ] sg[t+1][i] sg[t+1][i] f [ 0 ] [ i − 1 ] f[0][i-1] f[0][i1] f [ 1 ] [ i + 1 ] f[1][i+1] f[1][i+1]三个数求 m e x mex mex来更新 s g [ t ] [ i ] sg[t][i] sg[t][i]

当前行没有包含障碍的格子

在这种情况下,当一个棋子从上一行来到这一行时,假设来到了 ( x , y ) (x,y) (x,y),若选择往左走,来到 ( x , y − 1 ) (x,y-1) (x,y1),则 ( x , y ) (x,y) (x,y)就相当于变成了一个包含障碍的格子,这就转化为了包含障碍格子的情况。

我们考虑如何计算 S G SG SG值。当从 ( x , y ) (x,y) (x,y)走到 ( x , y − 1 ) (x,y-1) (x,y1)时,只能往左或往下走,也就是说我们要用 ( x + 1 , y − 1 ) (x+1,y-1) (x+1,y1) S G SG SG值和 ( x , y − 2 ) (x,y-2) (x,y2) S G SG SG值来更新 ( x , y − 1 ) (x,y-1) (x,y1) S G SG SG值。而 ( x + 1 , y − 1 ) (x+1,y-1) (x+1,y1) S G SG SG值在之前已经求出,所以我们需要求的就是 ( x , y − 2 ) (x,y-2) (x,y2) S G SG SG值。以此类推,我们一路向左推,最终要求的就是 ( x , y + 1 ) (x,y+1) (x,y+1) S G SG SG值。此时只能往下走,可以直接求出 S G SG SG值,再一路回推。

这样的话,求每个位置的 S G SG SG值的时间复杂度都是 O ( m ) O(m) O(m)的。我们考虑优化。

我们可以注意到,每个位置的 S G SG SG值是由三个数求 m e x mex mex得来,也就是说 S G SG SG值只会取 0 , 1 , 2 , 3 0,1,2,3 0,1,2,3四个数。

假设当前行为第 t t t行,设 g [ 0 / 1 / 2 / 3 ] [ j ] [ i ] g[0/1/2/3][j][i] g[0/1/2/3][j][i]的意义如下:

  • g [ 0 ] [ j ] [ i ] g[0][j][i] g[0][j][i]表示当位置 ( t , 1 ) (t,1) (t,1) S G SG SG值为 j j j时,一路往右回推到 i i i(也就是从棋子从 i i i往左走到 1 1 1),此时位置 ( t , i ) (t,i) (t,i) S G SG SG
  • g [ 1 ] [ j ] [ i ] g[1][j][i] g[1][j][i]表示当位置 ( t , m ) (t,m) (t,m) S G SG SG值为 j j j时,一路往左回推到 i i i(也就是从棋子从 i i i往右走到 m m m),此时位置 ( t , i ) (t,i) (t,i) S G SG SG
  • g [ 2 ] [ j ] [ i ] g[2][j][i] g[2][j][i]表示位置 ( t , i ) (t,i) (t,i) S G SG SG j j j时, i i i是从 ( t , 1 ) (t,1) (t,1)向左回推过来的,此时位置 ( t , 1 ) (t,1) (t,1)的值
  • g [ 3 ] [ j ] [ i ] g[3][j][i] g[3][j][i]表示位置 ( t , i ) (t,i) (t,i) S G SG SG j j j时, i i i是从 ( t , m ) (t,m) (t,m)向右回推过来的,此时位置 ( t , m ) (t,m) (t,m)的值

那么,我们分别将 g [ 0 ] [ j ] [ i ] g[0][j][i] g[0][j][i] g [ 1 ] [ j ] [ i ] g[1][j][i] g[1][j][i] g [ 2 ] [ j ] [ i ] g[2][j][i] g[2][j][i] g [ 3 ] [ j ] [ i ] g[3][j][i] g[3][j][i]求出来,然后用他们来 O ( 1 ) O(1) O(1)更新每个点的 S G SG SG值即可。

可以参考代码方便理解。

两种情况处理每行的时间复杂度都为 O ( m ) O(m) O(m),所以总时间复杂度为 O ( n m ) O(nm) O(nm)


code

#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int T,n,m,ans,sg[N+5][N+5],f[2][N+5],g[4][4][N+5];
char s[2*N+5][2*N+5];
int mex(int v1,int v2,int v3){for(int i=0;i<=3;i++){if(i!=v1&&i!=v2&&i!=v3) return i;}
}
int gt(int i){return (i-1)%m+1;
}
void solve1(int t){memset(f,0,sizeof(f));for(int i=1;i<=m;i++) s[t][i+m]=s[t][i];int fst=1;while(s[t][fst]!='#') ++fst;for(int l=fst,r;l<m+fst;l=r){r=l+1;while(r<m+fst&&s[t][r]!='#') ++r;if(r==l+1) continue;f[0][l+1]=mex(sg[t+1][gt(l+1)],-1,-1);for(int i=l+2;i<r;i++) f[0][i]=mex(f[0][i-1],sg[t+1][gt(i)],-1);f[1][r-1]=mex(sg[t+1][gt(r-1)],-1,-1);for(int i=r-2;i>l;i--) f[1][i]=mex(f[1][i+1],sg[t+1][gt(i)],-1);for(int i=l+1;i<=r-1;i++){int v1=-1,v2=-1;if(i>l+1) v1=f[0][i-1];if(i<r-1) v2=f[1][i+1];sg[t][gt(i)]=mex(v1,v2,sg[t+1][gt(i)]);}}
}
void solve2(int t){if(m==1){sg[t][1]=mex(sg[t+1][1],-1,-1);return;}memset(g,0,sizeof(g));for(int j=0;j<=3;j++){g[0][j][1]=j;g[1][j][m]=j;g[2][j][1]=j;g[3][j][m]=j;}for(int i=2;i<=m;i++)for(int j=0;j<=3;j++) g[0][j][i]=mex(g[0][j][i-1],sg[t+1][i],-1);for(int i=m-1;i>=1;i--)for(int j=0;j<=3;j++) g[1][j][i]=mex(g[1][j][i+1],sg[t+1][i],-1);for(int i=2;i<=m;i++)for(int j=0;j<=3;j++) g[2][j][i]=g[2][mex(j,sg[t+1][i-1],-1)][i-1];for(int i=m-1;i>=1;i--)for(int j=0;j<=3;j++) g[3][j][i]=g[3][mex(j,sg[t+1][i+1],-1)][i+1];for(int i=1;i<=m;i++){int v1=-1,v2=-1,now;int nxt=gt(i+1),ed=g[3][mex(sg[t+1][nxt],-1,-1)][nxt];if(i==1) v1=ed;else{if(i==m) now=mex(sg[t+1][1],-1,-1);else now=mex(sg[t+1][1],ed,-1);v1=g[0][now][i-1];}int lst=gt(i-1+m),bg=g[2][mex(sg[t+1][lst],-1,-1)][lst];if(i==m) v2=bg;else{if(i==1) now=mex(sg[t+1][m],-1,-1);else now=mex(sg[t+1][m],bg,-1);v2=g[1][now][i+1];}sg[t][i]=mex(v1,v2,sg[t+1][i]);}
}
int main()
{freopen("game.in","r",stdin);freopen("game.out","w",stdout);scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);memset(sg,-1,sizeof(sg));for(int i=1;i<=n;i++) scanf("%s",s[i]+1);for(int i=n;i>=1;i--){int fl=0;for(int j=1;j<=m;j++){if(s[i][j]=='#'){fl=1;break;}}if(fl) solve1(i);else solve2(i);}ans=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(s[i][j]=='B') ans^=sg[i][j];}}if(ans) printf("A\n");else printf("B\n");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/120888.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧公厕:细致入微的城市贴心服务与便捷方便的生活配套

在现代城市生活中&#xff0c;公厕作为重要的城市基础设施&#xff0c;一直是城市发展的关键环节之一。然而&#xff0c;传统的公厕常常存在着设施陈旧、管理不善和卫生状况差等问题&#xff0c;给市民的生活品质和城市形象带来了一定的影响。为了提供更好的城市公厕服务&#…

Python 框架学习 Django篇 (六) 数据表关联、ORM关联

在后端服务器开发中&#xff0c;特别是前后端分离的架构中数据库是非常重要的&#xff0c;后端主要就是负责管理数据&#xff0c;而我们经常使用的mysql、oracle 都是关系型数据库&#xff0c;什么是关系型数据库&#xff1f;就是建立在关系模型基础上的数据库&#xff0c;而最…

Sql Server中的表组织和索引组织(聚集索引结构,非聚集索引结构,堆结构)

正文 SqlServer用三种方法来组织其分区中的数据或索引页&#xff1a; 1、聚集索引结构 聚集索引是按B树结构进行组织的&#xff0c;B树中的每一页称为一个索引节点。每个索引行包含一个键值和一个指针。指针指向B树上的某一中间级页&#xff08;比如根节点指向中间级节点中的…

超全面测评!2023年最常用的15款原型设计工具

在互联网和软件行业中&#xff0c;原型设计是产品经理、交互设计师以及运营人员等职位必不可少的一门技能。原型设计工具的重要性也是人尽皆知&#xff0c;这都是因为原型设计工具是帮助设计者表达产品想法、功能设定及流程逻辑的最佳方式。 今天就为大家带来原型设计工具的相…

「林曦的亲子美育」讲讲关于阅读的那些事儿

「林曦的亲子美育」是“林曦的小世界”2023年策划的一档新栏目。林曦老师作为一个“小男生的妈妈”,在这些年分享了许多关于亲子教育的心得&#xff1a;以“美”作为连接和最高标准&#xff0c;会护持着小朋友的选择和人生。教育是一个生活的过程。做一餐饭、读一本书、看一张画…

HCL模拟器选路实验案例

此选路题目选自职业院校技能竞赛中的一道题比较考验思路&#xff0c;适合于参加新华三杯大赛以及网络专业的同学&#xff0c;当做练习题目进行解题​​​​​​​ 题目 1.S1、S2、R1、R2运行ospf进程100&#xff0c;区域0&#xff0c;R1、R2、R3、R4、R5运行ospf进程200&#…

Ocelot简易教程目录

Ocelot简易教程目录 这里写目录标题 Ocelot简易教程目录 Ocelot简易教程&#xff08;一&#xff09;之Ocelot是什么Ocelot简易教程&#xff08;二&#xff09;之快速开始1Ocelot简易教程&#xff08;二&#xff09;之快速开始2Ocelot简易教程&#xff08;三&#xff09;之主要特…

安装虚拟机找不到虚拟网啦1(eth1)不出现

一、安装虚拟机找不到虚拟网啦1&#xff08;eth1&#xff09;不出现 1、先安装virtualbox 2、再安装vagrant 3、在windows使用ipconfig没有VirtualBoxHost-OnlyNetWork解决方法 1) 解决办法 在windows的设置中找到 网络和Internet 选项&#xff0c;选择右侧 更改适配器选项 …

微信小程序开发之投票管理及小程序UI的使用

目录 一、小程序UI 1.讲述 2. 介绍vantWeapp 3. 使用vantWeapp 安装 构建 依赖 引用 二、后端 1. 后端实体对象 2. 后端接口 3. 实现类 4. 请求处理类 三、前端 1. 定义路径 2. 页面引用 3. 页面 4. 页面美化 5. 数据 6. 效果展示 一、小程序UI 1.讲述 小…

vue 项目中实现base64 加密 、解密

第一种方式&#xff0c;直接使用插件 js-base64 1、安装插件 npm install --save js-base642、插件引用 import { Base64 } from js-base643、加密、解密 const encodePwd Base64.encode(password);//加密 const decodePwd Base64.decode(encodePwd);//解密第二种&#x…

信息学奥赛一本通2061:【例1.2】梯形面积

2061&#xff1a;【例1.2】梯形面积 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 172550 通过数: 68183 【题目描述】 在梯形中阴影部分面积是150平方厘米&#xff0c;求梯形面积。 【输入】 (无&#xff09; 【输出】 输出梯形面积&#xff08;保留两位小数&a…

HarmonyOS开发:NodeJs脚本实现组件化动态切换

前言 上篇文章&#xff0c;我们使用NodeJs脚本完成了HarmonyOS项目的组件化运行&#xff0c;但是由于脚本是基于4.0.0.400版本的DevEco Studio开发的&#xff0c;可能在配置文件的修改上有些许差距&#xff0c;那么遇到这种情况怎么办&#xff0c;一种是再写一套针对性的脚本文…

【Oracle】[INS-30131]执行安装程序验证所需的初始设置失败。

这里写目录标题 一、问题描述1 报错内容1.1 无法从节点“kotin”检索 exectask 的版本1.2 工作目录"xxx"无法在节点"kotin"上使用 2 相关环境2.1 安装软件2.2 安装系统 3 解决思路分析 二、解决方案1 方案一、 满足验证条件 - 不换系统1.1 第一步、检查文件…

笔记 | MySQL 运维常用语句

1.导出整个库 mysqldump -u 用户名 -p –default-character-setlatin1 数据库名 > 导出的文件名(数据库默认编码是latin1) mysqldump -u wcnc -p smgp_apps_wcnc > wcnc.sql2.导出一个表 mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名 mysqldump -u wcnc…

p5.js 到底怎么设置背景图?

本文简介 点赞 关注 收藏 学会了 在 《p5.js 光速入门》 里我们学过加载图片元素&#xff0c;学过过背景色的用法&#xff0c;但当时没提到背景图要怎么使用。 本文就把背景图这部分内容补充完整&#xff0c;并且会提到在 p5.js 里使用背景图的一些注意点。 背景图的用法…

Oracle数据库基础

一、Oracle数据库介绍: Oracle数据库是由Oracle公司开发的关系型数据库管理系统(RDBMS),它是世界上最流行和广泛使用的商业数据库之一。Oracle数据库提供了可靠、高性能和安全的数据管理解决方案,被广泛应用于企业级应用程序和大型数据中心。 二、Oracle数据库各个版本的…

在虚拟环境中,通过pip安装tensorflow

目录 激活python虚拟环境&#xff0c;更新pip 通过pip 安装tensorflow 确定python版本&#xff1a; ​编辑安装tensorflow: ​编辑 为什么使用pip安装tensorflow? 激活python虚拟环境&#xff0c;更新pip 命令为python -m pip install --upgrade pip 通过pip 安装tensorf…

C语言之结构体和共用体详解

目录 结构体 结构体的定义和使用 结构体数组的使用 结构体指针的使用 结构体大小的计算 共用体 共用体的定义和使用 typedef用法详解 enum枚举类型 结构体 结构体的定义和使用 C语言的结构体&#xff08;Struct&#xff09;是一种自定义的数据类型&#xff0c;它允许…

时间、空间复杂度的例题详解

文章前言 上篇文章带大家认识了数据结构和算法的含义&#xff0c;以及理解了时间、空间复杂度&#xff0c;那么接下来来深入理解一下时间、空间复杂度。 时间复杂度实例 实例1 // 计算Func2的时间复杂度&#xff1f; void Func2(int N) {int count 0;for (int k 0; k <…

数据结构与算法之排序: 堆排序 (Javascript版)

排序 排序&#xff1a;把某个乱序的数组变成升序或降序的数组 (这里用数组来做举例) 堆排序 该排序属于 Selectionsort 选择排序的优化版本由于堆排序的查找过程从O(n)优化为O(logn)整体的排序时间复杂度为 O(nlogn)&#xff0c;这是排序算法中的最优解&#xff01;&#xf…