Luogu P10501 Cutting Game 题解
博弈论经典题目,考虑使用 SG 函数解决。
但是这一题和有向图游戏的定义不同,在有向图游戏不能操作者判负,而这一题中操作出某个状态者判胜。因此,我们需要进行转化。经典做法是往前推直到推出必败态作为有向图游戏的终点。
我们考虑什么样的情况可以剪出 的纸条,显然,当且仅当在 或 的纸条上可以剪出 的纸条。因此,这种情况下是先手必胜态。
往前推出必败态,就是要找到一个只能剪出 或 的纸条的状态。不难发现在 的纸条中都只能剪出 或 的纸条,因此它们是必败态。以它们作为有向图游戏的终点,即可按照有向图游戏的方式处理。
我们考虑枚举每个状态在哪一行或者哪一列剪开,之后就是两个剪纸子问题,求出它们的 SG 函数的值后用有向图游戏和异或起来就是当前状态的一个后继状态的 SG 函数值,求 mex 就行了。
注意每一步不会直接剪出 或 的纸条,因为会使对手直接获胜,所以代码实现时需要注意边界条件。下面给出转移式。
使用记忆化搜索预处理实现。
#include <bits/stdc++.h>
using namespace std;
long long n,m,x[300000],sg[300][300];
bool vis[300][300];
long long dfs(long long n,long long m)
{
if(n==2&&m==2)return 0;
if(n==2&&m==3)return 0;
if(n==3&&m==2)return 0;
if(vis[n][m])return sg[n][m];
vis[n][m]=1;
for(int i=2;i<n-1;i++)x[dfs(i,m)^dfs(n-i,m)]=1;
for(int i=2;i<m-1;i++)x[dfs(n,i)^dfs(n,m-i)]=1;
long long mex=0;
while(x[mex])mex++;
for(int i=2;i<n-1;i++)x[dfs(i,m)^dfs(n-i,m)]=0;
for(int i=2;i<m-1;i++)x[dfs(n,i)^dfs(n,m-i)]=0;
return sg[n][m]=mex;
}
int main()
{
for(int i=2;i<=200;i++)
for(int j=2;j<=200;j++)dfs(i,j);
while(scanf("%lld%lld",&n,&m)!=-1)
{
if(sg[n][m])printf("WIN\n");
else printf("LOSE\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探