取石子

每一堆数量都>1的话可以把合并操作和取石子看成一种操作,总操作数就是sum+n-1,为奇数就是Alice先手必胜,哪怕有一堆是2,Bob取后变为1,Alice也可以通过合并操作让1变成>1的数

可以分成两大板块a、b, a中方石子个数为1的,b中放石子个数>1的(合并操作也算进去),

共有5种操作

f(a, b)

1、a中取一个->f(a-1,b)

2、b中取一个->f(a,b-1)

3、a中合并一次,如果此时b为0->f(a-2,b+2),b非0->f(a-2, b+3)

4、b中合并一次->f(a,b-1)//与2式子相同,可化简为同一步

5、a与b合并一次->f(a-1,b+1)

注意5的操作要求a、b都大于0

接下来记忆化搜索即可

b减到1时需要划分到a堆里

cpp 复制代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
 
using namespace std;
 
typedef pair<int, int> PII;
typedef long long ll;

const int N = 55, M = 50060;

int f[N][M];

bool dp(int a, int b)
{
	int &v = f[a][b];
	if(v != -1)return f[a][b];
	if(!a)return v = b % 2;
	if(b == 1)a ++, b --;
	
	if(a && !dp(a - 1, b))return v = 1;
	if(b && !dp(a, b - 1))return v = 1;
	if(a >= 2)
	{
		int t = b + 2;
		if(b)t ++;
		if(!dp(a - 2, t))return v = 1;
	}
	if(a && b && !dp(a - 1, b + 1))return v = 1;
	
	return v = 0;
}

void solve()
{
	int n;
	cin >> n;
	int a = 0, b = 0;
	for(int i = 0; i < n; i ++)
	{
		int x;
		cin >> x;
		if(x == 1)a ++;
		else
		{
			if(b)b ++;
			b += x;
		}
	}
	if(dp(a, b))cout << "YES" << endl;
	else cout << "NO" << endl;
}

int main()
{
	IOS
	memset(f, -1, sizeof f);
	
	int _;
	cin >> _;
	while(_ --)
	{
		solve();
	}
	
	return 0;
}
相关推荐
szuzhan.gy19 分钟前
DS查找—二叉树平衡因子
数据结构·c++·算法
火云洞红孩儿43 分钟前
基于AI IDE 打造快速化的游戏LUA脚本的生成系统
c++·人工智能·inscode·游戏引擎·lua·游戏开发·脚本系统
一只码代码的章鱼1 小时前
排序算法 (插入,选择,冒泡,希尔,快速,归并,堆排序)
数据结构·算法·排序算法
青い月の魔女1 小时前
数据结构初阶---二叉树
c语言·数据结构·笔记·学习·算法
林的快手2 小时前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
FeboReigns2 小时前
C++简明教程(4)(Hello World)
c语言·c++
FeboReigns2 小时前
C++简明教程(10)(初识类)
c语言·开发语言·c++
千天夜2 小时前
多源多点路径规划:基于启发式动态生成树算法的实现
算法·机器学习·动态规划
zh路西法2 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
从以前2 小时前
准备考试:解决大学入学考试问题
数据结构·python·算法