概要
博弈论好有意思感觉以后可以用这招坑人了。。。。。。
思想本质其实还是贪心了,万法归贪嘛
首先是对于动态规划的贪心,但是限制比较大
void solve(){
win[0]=false;
//当轮到自己时没有硬币了,那么就是必输态
for(int j=1;j<=X;j++){
win[j]=false;
for(int i=0;i<K;i++){
//如果让对手达到必输态,那么我们就是必赢态了
win[j]|=A[i]<=j&&!win[j-A[i]];
}
}
}
对于高级”奇偶“的贪心(POJ 2484)
其实规则都可以转化成:
存在一堆石子,先手拿一个,后手拿一个,最后看看谁能拿到最后一个
这样奇偶性就能决定胜利与失败了
就如同 这个题:
A Funny Game
最终的策略就是你拿一个我也拿一个为最优策略,其实思路还要复杂一点但是问题本质还是奇偶问题(谁能将数据变为偶数谁就能必胜)
Nim值解析
首先该值使用了异或这个运算符,二进制中相同取0不同取1
当
a1^ a2 ^a3 ^…, ^an=0时 先手必输反之先手必赢
这是为什么呢?
因为若Nim为0,说明每一个二进制的1都有偶数个,所以无论先手取多少后手都可以取相同的个数,导致变为你拿一个我也拿一个的局势导致谁能维持偶数形式谁就赢。
Grundy数解析
其实Grundy数本质还是Nim的应用,最后还是要异或求Nim值
具体思路就是将抽象的数据,转化为可以使用异或计算的数值
对比:
Nim中有x颗石子的石子堆,能够转移成0,1,…,x-1
从Grundy值为x的状态出发,可以转移到Grundy值为0,1,…,x-1的状态
通俗理解就是Nim是可以取任意数量的石子从而可以使石子堆变为任意小于本身总量的x‘
但是Grundy值就是将石子堆本身具有的sum总量变为可以任意变化的x形式
于是转化算法如下
void solve(){
//0与0没区别
grundy[0]=0;
//计算grundy值
int max_x=*max_element(x,x+n);//找出石子堆的最大值
for(int j=1;j<=max_x;j++){
set<int>s;
for(int i=0;i<k;i++){
if(A[i]<=j)s.insert(grundy[j-A[i]]);//收集可以变化的数字
}
int g=0;
while(s.count(g)!=0)g++;
//计算能达到的等价x(要求操作后可以使该堆石子能变化为小于x的任意数字)
grundy[j]=g;
}
//使用Nim值判断胜负
int x1=0;
for(int i=0;i<N;i++)x1^=grundy[x[i]];
}