【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)
2018-04-06 22:33
302 查看
【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)
题面
BZOJDescription
菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且
这个格子的左侧及上方的所有格子内都有棋子。
棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij、Bij。在
游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所
有有白棋的格子上的Bij的和。
菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都
采用最优策略且知道对方会采用最优策略,那么,最终的结果如何
Input
第一行包含两个正整数n,m,保证n,m≤10。接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
第一个非负整数:其中第i行中第j个数表示Aij。
接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
第二个非负整数:其中第i行中第j个数表示Bij
n, m ≤ 10 , Aij, Bij ≤ 100000
Output
输出一个整数,表示菲菲的得分减去牛牛的得分的结果。Sample Input
2 32 7 3
9 1 2
3 7 2
2 3 1
Sample Output
2题解
考虑一下所谓的两个人都是走最优策略也就是对于第一个人,
它一定从当前局面可以到达的所有局面中,选择一个最大的走。
第二个人一定会从当前局面所有可以到达的局面中,选择一个最小的走。
(这就是所谓的\(min-max\)搜索???或者叫对抗搜索??)
考虑一下所有的状态,一定是一个从上往下的阶梯型
因为\(n,m<=10\)
所以我们可以用一个\(n\)位的\(m+1\)进制数把当前下完的轮廓给哈希一下。
那么,对于一个局面,我们可以做记忆化搜索,
我们只需要根据局面当前下子的是谁,决定这个状态是最大还是最小。这样用\(map\)压下当前所有状态,直接搜索即可。。
要是让我考我肯定做不出来
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 15 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } const int Base=11; map<ll,int> M; int ln[MAX],n,m; int A[MAX][MAX],B[MAX][MAX]; ll Hash(){ll ret=0;for(int i=1;i<=n;++i)ret=ret*Base+ln[i];return ret;} void UnHash(ll st){for(int i=n;i;--i)ln[i]=st%Base,st/=Base;} int Next(){int ret=0;for(int i=1;i<=n;++i)ret+=ln[i];return ret&1;} int dfs(ll st) { if(M.count(st))return M[st]; UnHash(st); int opt=Next(),ret=opt?1e9:-1e9; for(int i=1;i<=n;++i) if(ln[i-1]>ln[i]) { ln[i]++; ll now=Hash(); opt?ret=min(ret,dfs(now)-B[i][ln[i]]):ret=max(ret,dfs(now)+A[i][ln[i]]); ln[i]--; } return M[st]=ret; } int main() { n=read();ln[0]=m=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) A[i][j]=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) B[i][j]=read(); ll all=0; for(int i=1;i<=n;++i)all=all*Base+m; M[all]=0; dfs(0); printf("%d\n",M[0]); return 0; }
相关文章推荐
- BZOJ.5248.[九省联考2018]一双木棋chess(对抗搜索 记忆化)
- [BZOJ5248][九省联考2018]一双木棋(连通性DP,对抗搜索)
- [BZOJ5248] 2018九省联考 D1T1 一双木棋 | 博弈论 状压DP
- 【BZOJ5251】【八省联考2018】劈配(网络流,二分答案)
- 洛谷P4363 [九省联考2018]一双木棋chess 【状压dp】
- BZOJ5248:[九省联考2018]一双木棋——题解
- BZOJ_5249_Luogu_P4364_[2018多省省队联测]_IIIDX_九省联考2018_JLOI2018_线段树
- [BZOJ5249][九省联考2018]IIIDX(线段树)
- [BZOJ5250][九省联考2018]秘密袭击(DP)
- BZOJ5337 [TJOI2018] 碱基序列 【哈希】【动态规划】
- [九省联考2018] 一双木棋 chess
- [九省联考 2018]一双木棋chess
- [BZOJ5248][多省联测2018]双木棋chess
- bzoj 5248: [2018多省省队联测]一双木棋
- [BZOJ5251][九省联考2018]劈配(网络流)
- 【BZOJ3555】企鹅QQ,第一次正确的使用哈希A题
- 【BZOJ1053】【HAOI2007】反素数ant 打表。/搜索
- BZOJ 1024 搜索
- BZOJ 3643|Phi的反函数|搜索|线性筛法
- BZOJ 3555: [Ctsc2014]企鹅QQ 哈希