所谓博弈,就是两人轮流进行决策,并且两人都使用最优策略来获取胜利。通俗的说就是两个人都想获得胜利,两个人都有头脑,并且不会失误。博弈的次数是有限的,两人遵循的规则是相同的。
有一堆石子,共有n块,两个人轮流取石子,每次至少取1块,最多取m个,最后取光者获胜(假设A,B两个人,规定A先操作)。
(1)当n=(m+1)*k时,(k为任意正整数),当A先取石子时,A取X块石子,无论X为多少,B只要取(m+1-x),则B必胜,此时为A的必败态。
(2)当n=(m+1)*k+r(k,r为任意正整数,r不大于m),此时A先取r块,那么B始终处在(m+1)*k的状态,由(1)可知,此时A一定赢,为A的必胜态。
通过以上就可以变形从而解决很多问题。。
例1:假设有一个箱子,可以装n个物品,每次最多可以装m个,最少可以装1个,A,B轮流操作,最后装满箱子的人获胜。
伪代码如下:
if(n%(m+1))
A获胜
else
B获胜
例2:
假设一堆有n个物品,每次最多取m个,最少取1个,最后取光者输(A先进行)
伪代码:
if((n-1)%(m+1)==0)
B 获胜
else
A获胜
看完基本原理刷几道水题吧,啊哈哈。。。
HDU1846 http://acm.hdu.edu.cn/showproblem.php?pid=1846
代码如下:

1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 using namespace std; 5 int main() 6 { 7 int t,m,n; 8 cin>>t; 9 while(t--){ 10 cin>>n>>m; 11 if(n%(m+1)) 12 cout<<"first"<<endl; 13 else cout<<"second"<<endl; 14 } 15 }
这个是最基本的啦,直接套模板。
再看一个题吧
HDU1847 http://acm.hdu.edu.cn/showproblem.php?pid=1847
这个题就是在巴什博弈的模板的基础上小小的改动啦一下,思考一下就好啦。。
题目说每次取牌的数目只能是2的幂数,且每次Kiki先开始取牌,我们从特殊情况开始讨论
1.当牌数n就是2的幂数的时候,Kiki直接拿走所有的牌,此时Kiki获胜。
2.当牌数n不是恰好是2的幂数,这个时候如果把牌分成x个部分,每个部分都是由2的幂数组成,那么如果x为奇数,就是Kiki赢,否则就是Cici赢。
思路理解啦,咱们来看代码吧,这个思路是从学长那里借鉴来的,哈哈!!!!!!!!!!

1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1005; 7 bool used[maxn]; 8 void check() 9 { 10 int n; 11 memset(used,false,sizeof(used)); 12 for(int i=0;i<maxn;i++){ 13 if(!used[i]){ 14 int shu=1; 15 while(shu+i<maxn){ 16 used[shu+i]=true; 17 shu<<=1; 18 } 19 } 20 } 21 22 } 23 int main(){ 24 check(); 25 int m; 26 while(cin>>m){ 27 if(used[m]){ 28 cout<<"Kiki"<<endl; 29 30 } 31 else 32 33 cout<<"Cici"<<endl; 34 } 35 }
针对这道题,还有另外一种想法。。
题目说的是2的幂次,那么如果每次留给对手的都是3的倍数的话,对手如果取1,你就可以再取一点点,仍然留给对手3的倍数,如果对手取2的幂次,那么你就直接取1啦嘛。。
代码如下:

1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 int main(){ 7 int n; 8 while(cin>>n){ 9 if(n%3==0) 10 cout<<"Cici"<<endl; 11 12 13 else cout<<"Kiki"<<endl; 14 } 15 }