洛谷 P4363 [九省联考2018]一双木棋chess 解题报告
P4363 [九省联考2018]一双木棋chess
题目描述
菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。
落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且这个格子的左侧及上方的所有格子内都有棋子。
棋盘的每个格子上,都写有两个非负整数,从上到下第\(i\)行中从左到右第\(j\)列的格子上的两个整数记作\(A_{i,j},B_{i,j}\) 。在游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的\(A_{i,j}\)之和,牛牛的得分是所有有白棋的格子上的\(B_{i,j}\)的和。
菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都采用最优策略且知道对方会采用最优策略,那么,最终的结果如何。
输入输出格式
输入格式:
输入第一行包含两个正整数\(n,m\),保证\(n,m<=10\)。
接下来\(n\)行,每行\(m\)个非负整数,按从上到下从左到右的顺序描述每个格子上的 第一个非负整数:其中第\(i\)行中第\(j\)个数表示\(A_{i,j}\) 。
接下来\(n\)行,每行\(m\)个非负整数,按从上到下从左到右的顺序描述每个格子上的 第二个非负整数:其中第\(i\)行中第\(j\)个数表示\(B_{i,j}\) 。
输出格式:
输出一个整数,表示菲菲的得分减去牛牛的得分的结果。
说明:

也算是第一次做这样的博弈吧,省选划水的时候没做过状压也没做过博弈。好不容易YY出了\(n+m\)轮廓线处理的方法却不清楚怎么确定最优策略。结果15分的分类讨论分居然因为读入把A,B一起读了而爆0。。
先看看最优策略如何确定的:如果双方都采用最优策略且知道对方会采用最优策略。
由此我们得,我们要使用最优策略,首先要知道对方的最优策略,然后才能确定自己的最优策略。
但是如果我们只考虑前面的已经做的状态,是无法得知最优策略的。
这时候我们反其道而行之,把当前一步可以到达的局面看成一个子问题。这个子问题已经产生了答案,它是一个规模缩小版的但已经处理完了每一步的一个游戏。我们这一步可以进入这个子问题,但进入的入口并不唯一,我们对这个不唯一进行决策,找到对自己而言的局面最大化进入。而这个子问题的最小规模又是唯一确定的,也就是最后一步。所以我们的思路是,先通过记忆化搜索进入最后一步,然后像做树形DP那样在对搜索树进行回溯的时候更新答案。
对于两个人的具体策略而言,我们不妨把\(score_a-score_b\)压入转移方程,则\(A\)的目的是求\(score_a-score_b\)极大化,而\(B\)的目的是求\(score_a-score_b\)极小化,这就是\(max-min\)对抗式搜索模型。
我们再来分析一下每一步的状态:一个格子可以落子当且仅当这个格子内没有棋子且这个格子的左侧及上方的所有格子内都有棋子,题目中这样一句话给了我们一个轮廓线描述状态的启示,我们只能在这样的轮廓线上进行,用0描述竖着的轮廓线,用1描述横着的轮廓线,则状态可以被长为\(n+m\)的轮廓线唯一的表示
画图举个例子

轮廓线为1001101
当进行状态转移时,我们模拟一下可以发现,当某位上为1而这一位的更高一位上为0时,当我们把这两位取反就是把轮廓线向外扩张了一个。用轮廓线确定坐标也不难,我们从低位开始枚举,对每一位的0或1决定如何移动当前对应坐标即可
Code:
#include <cstdio>
const int inf=0x3f3f3f3f;
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int n,m,a[12][12],b[12][12],dp[1048578],used[1048578];
void init()
{
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]);
}
int dfs(int s,int who)
{
if(used[s])
return dp[s];
used[s]=1;
dp[s]=who?-inf:inf;
int x=1,y=m,tmp;
for(int i=0;i<n+m-1;i++)
{
if(((s>>i)&1)&&!((s>>i+1)&1))
{
tmp=s^(3<<i);
if(who)
dp[s]=max(dp[s],dfs(tmp,who^1)+a[x][y]);
else
dp[s]=min(dp[s],dfs(tmp,who^1)-b[x][y]);
}
if((s>>i)&1) y--;
else x++;
}
return dp[s];
}
int main()
{
init();
used[(1<<n+m)-(1<<n)]=1;
printf("%d\n",dfs((1<<m)-1,1));
return 0;
}
2018.7.6
洛谷 P4363 [九省联考2018]一双木棋chess 解题报告的更多相关文章
- 洛谷 P4363 [九省联考2018]一双木棋chess 题解
题目链接:https://www.luogu.org/problemnew/show/P4363 分析: 首先博弈,然后考虑棋盘的规则,因为一个子在落下时它的上面和左面都已经没有空位了,所以棋子的右下 ...
- 洛谷P4363 [九省联考2018]一双木棋chess 【状压dp】
题目 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子当且仅当这个 ...
- luogu P4363 [九省联考2018]一双木棋chess
传送门 对抗搜索都不会,我真是菜死了qwq 首先根据题目条件,可以发现从上到下每一行的棋子数是单调不增的,然后n m都比较小,如果把状态搜出来,可以发现合法状态并不多,所以可以用一个11进制数表示状态 ...
- 【题解】Luogu P4363 [九省联考2018]一双木棋chess
原题传送门 这道题珂以轮廓线dp解决 经过推导,我们珂以发现下一行的棋子比上一行的棋子少(或等于),而且每一行中的棋子都是从左向右依次排列(从头开始,中间没有空隙) 所以每下完一步棋,棋盘的一部分是有 ...
- P4363 [九省联考2018]一双木棋chess
思路 容易发现只能在轮廓线的拐点处落子,所以棋盘的状态可以用一个n+m长度的二进制数表示 转移就是10变成01 代码 #include <cstdio> #include <algo ...
- P4363 [九省联考2018]一双木棋chess(对抗搜索+记忆化搜索)
传送门 这对抗搜索是个啥玩意儿…… 首先可以发现每一行的棋子数都不小于下一行,且局面可由每一行的棋子数唯一表示,那么用一个m+1进制数来表示当前局面,用longlong存,开map记忆化搜索 然后时间 ...
- BZOJ.5248.[九省联考2018]一双木棋chess(对抗搜索 记忆化)
BZOJ 洛谷P4363 [Update] 19.2.9 重做了遍,感觉之前写的有点扯= = 首先棋子的放置情况是阶梯状的. 其次,无论已经放棋子的格子上哪些是黑棋子哪些是白棋子,之前得分如何,两人在 ...
- [九省联考2018]一双木棋chess——搜索+哈希
题目:bzoj5248 https://www.lydsy.com/JudgeOnline/problem.php?id=5248 洛谷P4363 https://www.luogu.org/prob ...
- P4363 [九省联考2018]一双木棋
题面 这种搜索要把后继状态都跑出来之后取Min/Max 也就是回溯的时候进行操作 记得用hash进行记忆化(用map不开O2会TLE) #include<iostream> #includ ...
随机推荐
- 传输控制协议--- Transmission Control Protocol (TCP)
Transmission Control Protocol (TCP) 用于网络通信的传输控制和网络协议套件,包括很多协议,其中最主要的是TCP和IP协议.TCP/IP属于UNIX类系统的内置协议,被 ...
- ats缓存规则
一. 用户访问过程:1. ats收到一个用户对web对象的请求;2. 使用该地址, ats尝试着在其对象数据库(缓存)中用被请求对象的地址来定位该对象;3. 如果对象在缓存中, ats会检查该对象是否 ...
- 从零开始的Python学习Episode 18——面向对象(1)
类与对象 类即类别.种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体. 类的定义 class 类名: 属性1 属性2 def 方法(self,ar ...
- Node.js文档和教程
七天学会NodeJS:https://nqdeng.github.io/7-days-nodejs/ Node入门:http://www.nodebeginner.org/index-zh-cn.ht ...
- spring boot之配置跨域
在启动类中配置 @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override p ...
- First Scrum Meeting (2015/10/18)
会议是在昨晚进行的,本来早就应该写博了,可惜今天校园网炸个不停= =.刚修好就赶紧来发博客. 会议基本要素 会议主题:爬虫项目的核心技术讨论以及项目初期的工作分配 会议时间:2015.10.18 19 ...
- React环境配置(第一个React项目)
使用Webpack构建React项目 1. 使用NPM配置React环境 NPM及React安装自行百度 首先创建一个文件夹,the_first_React 进入到创建好的目录,npm init,然后 ...
- 第三次作业---excel导入数据库及显示
好吧首先承认这次作业失败了,而且我并不知道原因.另外,我也没有采用PowerDesigner 设计所需要的数据库,代码就用了全部的时间.感觉自己就像一个刚学会爬着走路的小孩去参加一百一十米跨栏,能不能 ...
- 软工网络15团队作业4——敏捷冲刺日志的集合贴(Alpha阶段)
Alpha阶段 第 1 篇 Scrum 冲刺博客 第 2 篇 Scrum 冲刺博客 第 3 篇 Scrum 冲刺博客 第 4 篇 Scrum 冲刺博客 第 5 篇 Scrum 冲刺博客 第 6 篇 S ...
- 软工网络15团队作业8——Beta阶段敏捷冲刺(Day6)
提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 数据库整理. 吴慧婷:我的世界界面完成部分. 陈敏: 我的世界功能--学习情况功能完成. 吴雅娟:我的世界功能--学习 ...