BZOJ 1457 棋盘游戏 SG函数
2015-08-03 11:23
204 查看
题意:链接
方法: SG函数,SG表?
解析:
这题的题意给你构建的情况就已经非常的好了。
N个棋子之间互不影响,代表着N个局面互不影响。
然后呢,每个局面的棋子能走的点都是这个局面的子游戏,将所有的子游戏进行mex运算就能得到每个局面的sg值。
但是发现这样打出来的sg表是错误的,因为我们没有考虑一些必败态。
经画图分析等发现,如果先手先走,走到了点(x,y)
如果走到了x==y||x==0||y==0的情况,那么先手直接GG。显然先手是不会这么走的,则所有的人除非在不得已的情况下才会走这些点。
所以我们不妨把他们的sg值赋0。这些点是不会存在于这个游戏中的,除非初始棋子在这些点上。
考虑了这些条件就OK了。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1010 #define M 110 using namespace std; int t,n; int ssgg[M][M]; struct node { int x,y; }pt ; int sg(int x,int y) { if(x==0||y==0)return 0; if(x==y)return ssgg[x][y]=0; if(ssgg[x][y]!=-1)return ssgg[x][y]; bool v[10010]; memset(v,0,sizeof(v)); for(int k=1;;k++) { if(x-k<=0&&y-k<=0)break; if(x-k>0&&x-k!=y)v[sg(x-k,y)]=1; if(y-k>0&&y-k!=x)v[sg(x,y-k)]=1; if(x-k>0&&y-k>0)v[sg(x-k,y-k)]=1; } for(int i=0;;i++)if(!v[i])return ssgg[x][y]=ssgg[y][x]=i; } int main() { scanf("%d",&t); memset(ssgg,-1,sizeof(ssgg)); while(t--) { scanf("%d",&n); int flag=0; for(int i=1;i<=n;i++) { scanf("%d%d",&pt[i].x,&pt[i].y); if(pt[i].x==0||pt[i].y==0||pt[i].x==pt[i].y)flag=1; } if(flag) { puts("^o^"); continue; } int ans=0; for(int i=1;i<=n;i++) { ans^=sg(pt[i].x,pt[i].y); } if(ans==0)puts("T_T"); else puts("^o^"); } }
相关文章推荐
- TreeSet的简单使用
- Web.config中设置启用webservice远程调试访问
- CSS学习笔记
- redis安装
- 谁登录了你的linux
- java中repaint()定时刷面板问题及演示代码(附滚动条实现)
- 数据库设计中,多对多关系使用使用逗号分割关联讨论
- C语言中的const关键字
- Python中的字符串
- IOS得到所选择的背景图片的坐标颜色
- android samsung note3 device not found
- C#创建一个polygon类
- react-native试玩(2)
- RMB转换人民币大小金额
- hdu5200 Trees(逆向思维+离线处理)
- 读文件封装类
- 锦上
- Window10 安装问题汇总
- 官方摇杆使用
- 杭电 1312 Red and Black 递归 附翻译