BZOJ5248:[九省联考2018]一双木棋——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5248
https://www.luogu.org/problemnew/show/P4363#sub
菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且这个格子的左侧及上方的所有格子内都有棋子。棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij、Bij。在游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所有有白棋的格子上的Bij的和。菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都采用最优策略且知道对方会采用最优策略,那么,最终的结果如何
每次添加的棋子构成的形状永远都是一种类梯形的形状,可能状态会少些,更何况n和m才10,于是想到状压dp。
因为棋盘模型能够想到插头dp,那么轮廓线就是显然的棋子的边界。
于是向下的插头为0,向右的插头为1,显然状态才2^(n+m),记忆化搜即可。
题解讲完了接下来是吐槽时间:
woc我**是脑子抽了吧考试时候就写了一个对抗搜索???没写过插头dp可能不是很好想,但是我**好歹学过插头dp啊轮廓线我**怎么没想起来?
完后(知道题解后)我除了很zz的忘写了记忆化搜就是一次A了……
可能我的脑子天生不适合搞OI。
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
const int N=;
const int INF=1e9;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int n,m,a[N][N],b[N][N],f[<<(N*)][];
int dp(int s,int id){
if(f[s][id]!=INF)return f[s][id];
int c[N<<]={};
int l=-,tmp=s;
while(tmp){int t=tmp-tmp/*;c[++l]=t;tmp>>=;}
l=n+m-;
int ans=id?INF:-INF;
int x=,y=;
for(int i=;i<=l;i++){
if(!c[i])y++;
else x++;
if(i&&c[i-]&&(!c[i])){
tmp=s-(<<i>>)+(<<i);
if(!id)ans=max(ans,dp(tmp,id^)+a[n-x+][y]);
else ans=min(ans,dp(tmp,id^)-b[n-x+][y]);
}
}
return f[s][id]=(ans==INF||ans==-INF)?:ans;
}
int main(){
n=read(),m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
a[i][j]=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
b[i][j]=read();
for(int i=;i<(<<(n+m));i++)
f[i][]=f[i][]=INF;
int res=;
for(int i=;i<n;i++)res+=<<i;
printf("%d\n",dp(res,));
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ5248:[九省联考2018]一双木棋——题解的更多相关文章
- [BZOJ5248][九省联考2018]一双木棋(连通性DP,对抗搜索)
5248: [2018多省省队联测]一双木棋 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 43 Solved: 34[Submit][Status ...
- noi省选 [九省联考2018]一双木棋题解(状压dp)
比浙江简单多了........ 题目转送:https://www.luogu.org/problemnew/show/P4363 分析: 我们注意到n和m都很小,考虑一下状压dp. 显然,棋子摆成的形 ...
- 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告
P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...
- [九省联考2018]一双木棋chess——搜索+哈希
题目:bzoj5248 https://www.lydsy.com/JudgeOnline/problem.php?id=5248 洛谷P4363 https://www.luogu.org/prob ...
- Luogu4363 [九省联考2018]一双木棋chess 【状压DP】【进制转换】
题目分析: 首先跑个暴力,求一下有多少种状态,发现只有18xxxx种,然后每个状态有10的转移,所以复杂度大约是200w,然后利用进制转换的技巧求一下每个状态的十进制码就行了. 代码: #includ ...
- luogu P4363 [九省联考2018]一双木棋chess
传送门 对抗搜索都不会,我真是菜死了qwq 首先根据题目条件,可以发现从上到下每一行的棋子数是单调不增的,然后n m都比较小,如果把状态搜出来,可以发现合法状态并不多,所以可以用一个11进制数表示状态 ...
- [九省联考2018]一双木棋chess
题解: 水题吧 首先很显然的是状压或者搜索 考虑一下能不能状压吧 这个东西一定是长成三角形的样子的 所以是可以状压的 相邻两位之间有几个0代表他们差几 这样最多会有2n 然后就可以转移了 由于之前对博 ...
- 【题解】Luogu P4363 [九省联考2018]一双木棋chess
原题传送门 这道题珂以轮廓线dp解决 经过推导,我们珂以发现下一行的棋子比上一行的棋子少(或等于),而且每一行中的棋子都是从左向右依次排列(从头开始,中间没有空隙) 所以每下完一步棋,棋盘的一部分是有 ...
- P4363 [九省联考2018]一双木棋chess
思路 容易发现只能在轮廓线的拐点处落子,所以棋盘的状态可以用一个n+m长度的二进制数表示 转移就是10变成01 代码 #include <cstdio> #include <algo ...
随机推荐
- Unity编辑器 - 编辑器控制特效播放
编辑器控制特效播放 Unity的动画编辑器不能预览粒子系统的播放,为了方便预览特效,设想制作一个预览特效的工具,通常一个特效有三种组件: - Animation - Animator - Partic ...
- 利用maven进行项目管理
下面为maven项目管理的一个结构 首先pom是路径文件,我们在编译或是运行程序时调用到jdk或一些自己写的jar包时会需要指明物理路径,这里的pom是一样的道理,同时在maven的管理下多出来了一些 ...
- LeetCode 107 ——二叉树的层次遍历 II
1. 题目 2. 解答 与 LeetCode 102 --二叉树的层次遍历 类似,我们只需要将每一层的数据倒序输出即可. 定义一个存放树中数据的向量 data,一个存放树的每一层数据的向量 level ...
- Python+Opencv实现把图片转为视频
1. 安装Opencv包 在Python命令行输入如下命令(如果你使用的Anaconda,直接进入Anaconda Prompt键入命令即可.如果你不知道Anaconda是什么,可以参考王树义老师的文 ...
- ThinkPHP - 2 - SAE(新浪云)部署
ThinkPHP3.2核心内置了对SAE平台的支持(采用了应用模式的方式),具有自己的独创特性,能够最大程度的使用ThinkPHP的标准特性,让开发人员感受不到SAE和普通环境的差别.甚至可以不学习任 ...
- 《剑指Offer》题十一~题二十
十一.旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组{3, 4, 5, 1, 2}为{ ...
- 左值&右值
一.引子 我们所谓的左值.右值,正确的说法应该是左值表达式.右值表达式. 因为C++的表达式不是左值就是右值. 在C中,左值指的是既能够出现在等号左边也能出现在等号右边的表达式,右值指的则是只能出现在 ...
- Python练习—循环
1.输入n的值,求出n的阶乘. s=1 n = int(input("请输入一个数")) for i in range(1,n+1): s=s*i print(s) 2.折纸上月球 ...
- Java中I/O流之轮换流
Java 中的轮换流: 非常有用,可以把一个字节流转换成字符流. inputStreamReader, outputStreamReader Demo_1: import java.io.*; cla ...
- iOS-获取webView的高度
- (void)webViewDidFinishLoad:(UIWebView *)wb{ //方法1 CGFloat documentWidth = [[wb stringByEvaluatingJ ...