题解 P2575 高手过招 (二进制压缩+记忆化sg/模型转换阶梯nim)

博客介绍了如何运用二进制压缩和阶梯nim模型解决一个n*20棋盘的博弈问题。每行的棋子移动受特定规则限制,通过将问题分解为n个子游戏并利用sg定理,结合二进制压缩表示状态,最终转化为阶梯nim游戏进行求解。博主分享了暴力sg解法的失败经历,并提供了正确解题思路和代码实现。
摘要由CSDN通过智能技术生成

题目源自洛谷

题目大意:
n*20的棋盘,每行有若干个棋子。对于一个棋子,能将它向右移动一格,如果右边有棋子,则向右跳到第一个空格,如果右边没有空格,则不能移动这个棋子,如果所有棋子都不能移动,那么将输掉这场比赛。

解题思路:

  • 思路1:暴力sg

根据题意可知每行进行操作都是独立的,所以整个游戏又可分为n个子游戏,这是sg定理的第一步。
下一步考虑每个子游戏的状态。可知当棋子紧邻着排在左边的时候为必败态,而其他状态的后继可以通过枚举每个棋子向右走一步得到。这样通过sg解题就差最后一步如何表示状态了,每行只有20个固定的格子,每个格子只有有无棋子两种状态,于是就可以直接上二进制压缩了。

代码:

//bug1:递归过程中使用stl爆栈导致tle
//bug2:递归参数使用全局数组导致数值紊乱wa
//bug3:寻找mex值时未考虑后继状态sg值会重复导致wa
//bug4:忽略else会和最临近的if对应导致结构错误
//以上bug已全部修复
#include <bits/stdc++.h>
#define int long long
#define BS 1048576
using namespace std;

int sg[2000005];

int dfs(int x)
{
   
	if(sg[x]!=-1) return sg[x];

	int a[25],cnt=0;
	memset(a,-1,sizeof(a));
	//从右到左第i个位置
	for(int i=1;i<=20;i++)
	{
   
		int next=x;						//next代表后继状态
		if(((x>>(i-1))&1)){
   				//如果第i个位置为1
			next^=(1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值