sg(Sprague-Grundy)函数 小结
2015-07-10 20:21
597 查看
sg(Sprague-Grundy)函数
sg值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。
后继点:也就是按照题目要求的走法,能够走一步达到的那个点。
sg函数值的性质:
sg(x)==0 必败点
sg(x)>0 必胜点
求单个sg函数值
预处理sg值
例子:
hdu 1847
题意:
1. 总共n张牌;
2. 双方轮流抓牌;
3. 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4. 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明,并且每次都是Kiki先抓牌,请问谁能赢呢?
限制:
1 <= n <= 1000
思路:
sg函数
sg值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。
后继点:也就是按照题目要求的走法,能够走一步达到的那个点。
sg函数值的性质:
sg(x)==0 必败点
sg(x)>0 必胜点
求单个sg函数值
int sg[MAXN]; int get_sg(int x, int n){ if(sg[x]!=-1) return sg[x]; bool vis[105]={0}; for(int i=0;i<n;++i){ int tmp = a[i]; //tmp是转移的下一个状态的步数 if(x >= tmp){ sg[x - tmp] = get_sg(x - tmp, n); vis[sg[x - tmp]] = 1; } } for(int i=0;;++i) if(!vis[i]) return sg[x]=i; } void init(){ memset(sg,-1,sizeof(sg)); sg[0]=0; }
预处理sg值
void get_sg(){ sg[0]=0; for(int i=1;i<N;++i){ set<int> s; for(int j=0;j<10;++j){ int tmp=(1<<j); //tmp是转移的下一个状态的步数 if(i >= tmp) s.insert(sg[i - tmp]); } int g=0; while(s.count(g)!=0) ++g; sg[i]=g; } }
例子:
hdu 1847
题意:
1. 总共n张牌;
2. 双方轮流抓牌;
3. 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4. 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明,并且每次都是Kiki先抓牌,请问谁能赢呢?
限制:
1 <= n <= 1000
思路:
sg函数
/*hdu 1847 题意: 1. 总共n张牌; 2. 双方轮流抓牌; 3. 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…) 4. 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者; 假设Kiki和Cici都是足够聪明,并且每次都是Kiki先抓牌,请问谁能赢呢? 限制: 1 <= n <= 1000 思路: sg函数 */ #include<iostream> #include<cstdio> #include<cstring> #include<set> using namespace std; const int N=1005; const int M=105; int sg ; /*int get_sg(int x){ if(sg[x]!=-1) return sg[x]; bool vis[M]; memset(vis,0,sizeof(vis)); for(int i=0;i<10;++i){ int tmp = (1<<i); if(x >= tmp){ sg[x - tmp] = get_sg(x - tmp); vis[sg[x - tmp]] = 1; } } for(int i=0;;++i) if(!vis[i]) return i; } void get_sg(){ sg[0]=0; for(int i=1;i<=1000;++i){ sg[i]=get_sg(i); } }*/ void get_sg(){ sg[0]=0; for(int i=1;i<N;++i){ set<int> s; for(int j=0;j<10;++j){ int tmp=(1<<j); if(i >= tmp) s.insert(sg[i - tmp]); } int g=0; while(s.count(g)!=0) ++g; sg[i]=g; } } void init(){ memset(sg,-1,sizeof(sg)); } int main(){ init(); get_sg(); int n; while(scanf("%d",&n)!=EOF){ if(sg ==0) puts("Cici"); else puts("Kiki"); } return 0; }
相关文章推荐
- HDOJ 1047 Integer Inquiry
- UI-UIColor-initWithRed:green:blue:alpha:调研
- UI编程_UILabel及其属性
- 关于String Stringbuffer StringBuilder
- mosquitto配置与使用
- java序列化和serialVersionUID
- EASYUI之Layout
- Java中序列化的serialVersionUID作用
- ZOJ 3757 Alice and Bob and Cue Sports
- iOS中UIWindow的用法(一)
- IOS--UI--LessonUIControl UIImageView/ UISegmentedControl
- quick3x_保证下标顺序排列,删除table中的元素
- Builder模式
- UIAlertView和UIActionSheet
- Flash Builder4编译慢报java heap space堆空间异常错误的解决方法
- UI 设计师的好网站
- BlockingQueue及其各个实现的分析整理
- Exynos4412 Android4.4 HDMI Porting Guid 第三篇
- Exynos4412 Android4.4 HDMI Porting Guid 第二篇
- HTC T328W刷机包 仿三星S5 UI美化 精简 S5落下