Acwing 893. 集合-Nim游戏

一直在用考的少的理由,不学博弈论(game)。不学还是不行啊,先学个sg记忆化状态
1.sg()函数是递归求解某个状态sg值的过程,fg[]用来记忆化。
2.每个sg函数可以理解为一张有向无环图,每次遍历他的出边
3.求出每个堆的sg值后,再用尼姆博弈基本定理。

int s[105], fg[10010];
int n, m;
int sg(int x)
{
	if (fg[x] != -1)return fg[x];//搜到过,记忆化就是棒
	unordered_set<int> st;
	f(i, 1, m)//拓展他的可能出边
	{
		int now = s[i];
		if (x >= now)st.insert(sg(x - now));//递归并维护一个MEX数组
	}
	for (int i = 0;;++i)
		if (!st.count(i))
			return fg[x] = i;//找到mex,记忆化,并返回
}
int main()//sg函数实质是记忆化搜索,f[N]存每种状态的值,对每个sg求拓展它能到达的状态,然后对每张图进行尼姆博弈
{		
	cin >> m;
	f(i, 1, m)cin >> s[i];//可能状态转移价值
	cin >> n;
	int x;
	int ans = 0;
	memset(fg, -1, sizeof fg);//记忆化数组
	f(i, 1, n)
	{
		cin >> x;
		ans ^= sg(x);
	}
	if (ans == 0)puts("No");
	else puts("Yes");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值