ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

# [$Solution$] [九省联考 $2018$] 一双木棋($chess$)

2021-03-09 14:34:07  阅读:124  来源: 互联网

标签:int Solution blog 木棋 state 2303445 棋盘 联考 dp


# [$Solution$] [九省联考 $2018$] 一双木棋($chess$)

### 题意:

菲菲和牛牛在一块棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。

棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。

落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且这个格子的左侧及上方的所有格子内都有棋子。

棋盘的每个格子上,都写有两个非负整数

在游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上数值的和。

菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都采用最优策略且知道对方会采用最优策略,那么,最终的结果如何?

### 状态设计:

由于n,m范围较小,不难想到状压dp,但是显然不可能记录整个棋盘。

有考虑到题目中说到左边和上方都要选,那么不能想到轮廓线$DP$。

将横着的棋盘轮廓设为$0$,竖着的棋盘轮廓设为$1$,用一个十进制整数表示从左下到右上的一条轮廓线

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210008072-1777774707.png)

 

 

例如对于这张棋盘,用二进制表示则为$00101$

 

接下来以样例为例,解释具体情况:

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210008312-1578509225.png)

 

初始情况,棋盘为:$11000$,每一次寻找轮廓线中的所有向内凹的拐角(因为只有上左都被选过之后这个点才可以被选),例如在第一行第一列处进行dp,进入下一个状态。

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210008741-1898668714.png)

第一步:$10100$

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210008944-1098649872.png)

 

第二步:$10010$

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210009101-460574360.png)

 

第三步:$01010$

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210009308-807405269.png)

 

 

第四步:$01001$

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210009488-1632535067.png)

 

第五步:$00101$

 

![](https://www.icode9.com/i/l/?n=20&i=blog/2303445/202103/2303445-20210306210009662-520943471.png)

 

第六步:$00011$
$\\$
考虑这整个过程,就是一个将$10$的二进制数,变成$01$

所以状态设计为

$dp[state]$表示"当棋盘状态为$state$时先手得分与后手得分之差的最大值"。

这样做的好处是不用分情况讨论,不管是莉莉还是牛牛,其实本质上想得到的都是自己的得分减去对方得分的差最大。

### 状态转移方程:$dp[state]=max(dp[state],w[who][x][y]-dfs(next,who $^$ 1))$

//$next$表示在内拐点处落子后的情况。

### 边界条件:

```c++
if(i==n&&j==m)return dp[state]=0;
```

### AC CODE:

```c++
#include<bits/stdc++.h>
#define isnum(ch) ('0' <= ch && ch <= '9')
using namespace std;
int n,m,w[2][11][11];
int dp[1<<(20)];
int dfs(int i,int j,int who,int state)
{
if(i==n&&j==m)return dp[state]=0;
if(dp[state])return dp[state];
int res=-1e9;
int x=n+1,y=1,tstate;
for(int k=0;k<n+m-1;k++)
{
if((1<<k)&state)x--;//得到现在的棋盘状态
else y++;
if(!(((1<<k)&state)>0&&((1<<k+1)&state)==0))continue;
tstate=state^(3<<k);//得到下一步的棋盘状态
res=max(res,w[who][x][y]-dfs(x,y,who^1,tstate));//状态转移
}
return dp[state]=res;
}
signed main()
{
cin>>n>>m;
for(int k=0;k<=1;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>w[k][i][j];
int s=0;
for(int i=1;i<=n;i++)s^=1<<i-1;
cout<<dfs(1,1,0,s)<<endl;
return 0;
}
```

标签:int,Solution,blog,木棋,state,2303445,棋盘,联考,dp
来源: https://www.cnblogs.com/frsmt/p/14505330.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有