大白书 2.4节 组合游戏(博弈论)
2015-12-04 14:20
369 查看
大白书 2.4节 组合游戏
博弈论笔记:
1)必胜必败状态:
a)一个状态为必胜状态,充要条件是后续状态有一个必败状态
b)一个状态为必败状态,充要条件是后续状态全是必胜状态
2)SG函数
a)定义:SG[i] = {所有i的后继SG值中,不在这些值之中的最小非负整数}
b)一个状态为必败状态,当且仅当这个状态的SG值为0
c)通常可以用暴力的方法求出参见第二道题,数据过大时参见第一道题
3)Nim和与SG函数的应用
a)Nim和:一个父游戏的状态等于子游戏状态的异或和。
b)一个游戏的SG值,等于所有子游戏的SG值的异或和
UVA 1146
看的题解
找规律,n为偶数SG值为n/2,奇数为SG[i] = SG[i/2]
源码:
UVA 10561
看的题解和别人代码
对于一个X,存在控制区间即[x-2,x+2],在这个区间内放X就输了。
然后根据这个性质得出SG函数以及的特判输赢的情况。
然后枚举每个不在控制区间、不为X的位置变成1后SG是否为0,得出所有位置的解。
源码:
博弈论笔记:
1)必胜必败状态:
a)一个状态为必胜状态,充要条件是后续状态有一个必败状态
b)一个状态为必败状态,充要条件是后续状态全是必胜状态
2)SG函数
a)定义:SG[i] = {所有i的后继SG值中,不在这些值之中的最小非负整数}
b)一个状态为必败状态,当且仅当这个状态的SG值为0
c)通常可以用暴力的方法求出参见第二道题,数据过大时参见第一道题
3)Nim和与SG函数的应用
a)Nim和:一个父游戏的状态等于子游戏状态的异或和。
b)一个游戏的SG值,等于所有子游戏的SG值的异或和
UVA 1146
看的题解
找规律,n为偶数SG值为n/2,奇数为SG[i] = SG[i/2]
源码:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <iostream> #include <string> using namespace std; #define LL long long LL sg(LL u) { if(u % 2 == 0) return u / 2; return sg(u / 2); } int main() { int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); LL state = 0; while(n--){ LL u; scanf("%lld", &u); state ^= sg(u); } if(state == 0) printf("NO\n"); else printf("YES\n"); } return 0; }
UVA 10561
看的题解和别人代码
对于一个X,存在控制区间即[x-2,x+2],在这个区间内放X就输了。
然后根据这个性质得出SG函数以及的特判输赢的情况。
然后枚举每个不在控制区间、不为X的位置变成1后SG是否为0,得出所有位置的解。
源码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <iterator> using namespace std; const int MAXN = 200 + 5; int vis[MAXN]; int sg[MAXN]; void init() { sg[0] = 0; sg[1] = sg[2] = sg[3] = 1; for(int i = 4 ; i < MAXN ; i++){ memset(vis, 0, sizeof(vis)); for(int j = 1 ; j <= i ; j++){ ///枚举以那个点为划分点,然后[i-2,i+2]均失效 int l = max(0, j - 3); int r = max(0, i - j - 2); // if(i == 5){ // printf("l = %d, r = %d\n", l, r); // } vis[sg[l] ^ sg[r]] = 1; } for(int j = 0 ; ; j++){ if(vis[j] == 0){ sg[i] = j; break; } } } } char op[MAXN]; int ts[MAXN], s[MAXN]; int n; vector<int>ans; bool check1() { int ok = 0; ans.clear(); for(int i = 1 ; i <= n ; i++){ if(i > 2 && ts[i - 2] == 1 && ts[i - 1] == 1) ok = 1, ans.push_back(i); if(i <= n - 2 && ts[i + 1] == 1 && ts[i + 2] == 1) ok = 1, ans.push_back(i); if(i < n && i > 1 && ts[i] == 0 && ts[i - 1] == 1 && ts[i + 1] == 1) ok = 1, ans.push_back(i); } return ok; } int SG() { int state = 0; int cnt = 0; // printf("/***"); // for(int i = 1 ; i <= n ; i++) printf("%d ", s[i]); // printf("***///\n"); for(int i = 1 ; i <= n ; i++){ if(s[i] == 1){ // printf("cnt = %d\n", cnt); state ^= sg[cnt]; cnt = 0; } else cnt++; } // printf("cnt = %d\n", cnt); state ^= sg[cnt]; // printf("state = %d\n", state); return state; } int main() { // freopen("UVA 10561.in", "r", stdin); init(); // printf("sg[5] = %d\n", sg[5]); int T; scanf("%d", &T); while(T--){ scanf("%s", op); n = strlen(op); for(int i = 0 ; i < n ; i++){ if(op[i] == 'X') ts[i + 1] = 1; else ts[i + 1] = 0; } for(int i = 1 ; i <= n ; i++){ s[i] = 0; for(int j = max(1, i - 2) ; j <= min(n, i + 2) ; j++){ if(ts[j] == 1){ s[i] = 1; break; } } } if(check1()){///第一步即胜利 printf("WINNING\n"); vector<int>::iterator newend = unique(ans.begin(), ans.end()); ans.erase(newend, ans.end()); int f = 1; for(vector<int>::iterator it = ans.begin() ; it != ans.end() ; it++){ if(f) f = 0; else printf(" "); printf("%d", *it); } printf("\n"); continue; } else if(SG() == 0){ printf("LOSING\n\n"); } else{ // printf("///***"); // for(int i = 1 ; i <= n ; i++) printf("%d ", s[i]); // printf("***///\n"); ans.clear(); for(int i = 1 ; i <= n ; i++){ if(s[i] == 0){ memcpy(ts, s, sizeof(ts)); ///ts用于保存s的初始状态 for(int j = max(i - 2, 1) ; j <= min(i + 2, n) ; j++) s[j] = 1; // printf("i = %d, SG() = %d\n", i, SG()); if(SG() == 0) ans.push_back(i); memcpy(s, ts, sizeof(ts)); } } printf("WINNING\n"); int f = 1; for(vector<int>::iterator it = ans.begin() ; it != ans.end() ; it++){ if(f) f = 0; else printf(" "); printf("%d", *it); } printf("\n"); } } return 0; }
相关文章推荐
- 面试时必问题:接口和抽象类 有什么区别??
- Xcode7.1请求网络数据
- 各种高性能几何图形算法 如offset/分段拟合/nfp(no-fit-polygon)算法等
- viewpager 滑动 卡死 死机
- 自定义控件解决重复编码问题
- IndexedColors 的颜色样式 POI
- 编译安装nutch2.3和hbase0.98.8集成
- OC中的面向对象编程思想<一>
- ExtJS 4无限制滚动条的Grid
- iOS问题处理:如何在Mac下显示Finder中的所有文件
- Ubantu下面命令听歌(豆瓣fm)
- 公钥与私钥(转)
- epoll + 多线程实现并发网络连接处理
- 简要了解jQuery移动web开发的响应式布局设计
- Undefined symbols for architecture i386: _OBJC_CLASS_$_SKPSMTPMessage", referenced from: error
- 史上最全的 Java 新手问题汇总
- android典型代码系列(十九)------将一个数组复制成为另外一个数组的方法
- 制作可用grub引导Linux系统的磁盘映像文件 二
- 一维数组和指针数组和数组指针,以及扩展到二维数组和二级指针的分析和区别
- C# BackgroundWorker的使用【转-http://www.cnblogs.com/tom-tong/archive/2012/02/22/2363965.html】