[BZOJ5248][2018九省联考]一双木棋
题目描述
https://www.lydsy.com/JudgeOnline/problem.php?id=5248
Solution
我们首先考虑放棋子的操作
发现它一定放棋子的部分是一个联通块,不放棋子的是一个联通块
所以 我们考虑怎么表示这个轮廓
分析一下 N,M<=10 ?!
状态压缩?大爆搜?
然后我选择了状压…[听说大爆搜+hash也能做x]
用一串01串表示这个轮廓 表示从右上开始的一条路径,0表示向左走一步,1表示向下走一步,这样就可以通过一串0和1表示一个轮廓
每次的操作就是把一个01[左1下1]变成一个10[下1左1]
然后就是解决博弈的问题,理性分析[感性理解]一下 用dp[st]表示轮廓线状态为st的时候 最小化得分的差值
然后再感性理解一下
因为后手在第二步时 有办法选择对自己最优的情况进行转移,所以后手的转移就从他所能到达的状态选择一个最优的状态转移过来,如果当前是先手,就从当前可以到达的状态最劣的状态转移过来[感性理解x]
因为直接转移的话层次不是很显然,这里采取记忆化搜索实现这个dp[代码细节还是挺多的x]
Code
- #include <bits/stdc++.h>
- using namespace std;
- int N,M;
- bool used[5050006];
- int dp[5050006],qwq;
- int A[25][25],B[25][25];
- int dfs(int st)
- {
- if (used[st])
- return dp[st];
- int x=1,y=N+1,Con=0;
- int &ans=dp[st];
- used[st]=1;
- for (int i=0;i<qwq;i++)
- if (st&(1<<i)) Con+=y-1;
- else y--;
- y=N+1;
- ans=-1e9;
- if (st&1) x++;
- else y--;
- for (int i=1;i<qwq;i++)
- {
- if ((st&(1<<i))&&!(st&(1<<(i-1))))
- {
- if (Con%2==0)
- ans=max(-dfs(st^(1<<i)^(1<<(i-1)))+A[y][x],ans);
- else ans=max(-dfs(st^(1<<i)^(1<<(i-1)))+B[y][x],ans);
- }
- if (st&(1<<i))
- x++;
- else y--;
- }
- return ans;
- }
- int main()
- {
- scanf("%d%d",&N,&M);
- qwq=N+M;
- used[(1<<M)-1]=1;
- 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]);
- cout<<dfs(((1<<(N+M))-1)^((1<<N)-1));
- return 0;
- }
干啥啥不行
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?