[BZOJ3895]取石子(博弈+记搜)
来源:互联网 发布:用php写一个 编辑:程序博客网 时间:2024/06/18 00:16
题目描述
传送门
题解
我们可以通过石子的堆数和每一堆的个数计算出剩余的操作数,显然操作数为奇先手必胜,为偶先手必败。
若将=1的石子堆单独考虑,对于若干堆>1的石子,操作数为
那么我们可以记f[a][b]表示有a堆=1的石子,>1的石子操作数为b的状态(1表示先手必胜,0表示先手必败),然后进行记搜,对于a!=0的情况分类讨论,即可得出正确的解。
代码
#include<iostream>#include<cstring>#include<cstdio>using namespace std;int T,n,x;int f[100][51000];inline int dp(int a,int b){ //如果没有石子数为1的堆,则操作数为奇先手必胜,为偶先手必败 if (a==0) return b&1; //若操作数为1此时b部分只有1个石子 归到a里面去 if (b==1) return dp(a+1,0); if (~f[a][b]) return f[a][b]; int &re=f[a][b]; //将一个石子数为1的堆和一个不为1的堆合并 if (a&&b&&!dp(a-1,b+1)) return re=1; //将两个石子数为1的堆合并 if (a>=2&&!dp(a-2,b+2+(b?1:0))) return re=1; //从石子数为1的堆里拿走一个 if (a&&!dp(a-1,b)) return re=1; //将两个石子不为1的堆合并或 从石子数不为1的堆里拿走一个 if (b&&!dp(a,b-1)) return re=1; return re=0;}int main(){ scanf("%d",&T); memset(f,-1,sizeof(f)); while (T--) { scanf("%d",&n); int a=0,b=0; for (int i=1;i<=n;++i) { scanf("%d",&x); if (x==1) a++; else b+=x+1; } b--; puts(dp(a,b)?"YES":"NO"); }}
总结
1、博弈的题考虑记搜
0 0
- [BZOJ3895]取石子(博弈+记搜)
- 【BZOJ3895】取石子
- 【bzoj3895】【取石子】【博弈论+记忆化搜索】
- 博弈(取石子)专题
- 博弈(各类取石子)
- 取石子游戏(博弈)
- 【codevs3153】【BZOJ3895】取石子游戏,博弈论之记忆化搜索
- 取石子(一) 23 (博弈)
- 取石子游戏(博弈算法)
- POJ1067 取石子游戏 (威佐夫博弈)
- POJ 1067 取石子游戏 (博弈)
- 取石子游戏(博弈类)
- 2516取石子游戏(简单博弈)
- hdu 2516 取石子游戏(博弈)
- hdu 2516 取石子游戏 (博弈)
- HDOJ 取石子游戏(威佐夫博弈)
- 对称博弈--取石子(七)
- 取石子游戏(威佐夫博弈)
- 解决虚拟机提示VMwareWorkstationcannotconnecttothevirtualmachine的问题
- spring声明式事物管理配置和对c3p0连接池的详细配置
- strstr函数的精彩之处
- mongodb 计算坐标距离
- Android工具类---格式化文件
- [BZOJ3895]取石子(博弈+记搜)
- SPOJ SOPARADE(JZOJ 4696 第四次忍者大战) 根据条件构图跑2-SAT
- HDU 1556 Color the ball
- JZOJ4703 Buy
- 指数级增长背后,滴滴出行业务系统的架构升级
- Java反射与泛型的本质
- linux crontab
- hdoj 5839 Special Tetrahedron 叉积点积判断四点共面模板
- 多个线程之间如何进行通信