Bash游戏
有1堆石子,共n颗,每次可取1~k颗,先拿完者胜
若n%(k+1)==0,则先手必败
#include<bits/stdc++.h> using namespace std; int main() { int T; cin>>T; while(T--) { int n,k; scanf("%d%d",&n,&k); if(n%(k+1)==0) printf("B "); else printf("A "); } }
Bash游戏_进阶
题目链接(这是个坑)
有1堆石子,共n颗,每次可取k(属于集合f)颗,先拿完者胜
打表找好规律就好了,下面是打表函数
#include<bits/stdc++.h> using namespace std; //const int N=; int vis[100]; //int f[N]={}; int main() { for(int i=1;i<90;i++) for(int j=0;f[j]<=i&&j<N;j++) { if(vis[i-f[j]]==0) vis[i]=1; } for(int i=0;i<90;i++) printf("i=%d:vis[i]=%d ",i,vis[i]); }
总结:此类博弈不需要考虑sg函数,只需要确定必胜态和必败态,解题思路一般为打败先打表找规律,而后找规律给出统一的公式。打表方式:给定初始条件,然后从低到高枚举某一状态的所有次态,若有存在必败次态,则当前状态为必胜态,否则当前状态必败。
===========================================================================================
Nim游戏
有n堆石子,每堆有a[i]个石子,先拿完者胜
若异或和不为0,则先手必胜
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; int ans=0; while(n--) { int t; cin>>t; ans^=t; } if(ans==0) printf("B "); else printf("A "); }
Nim游戏_进阶
有n堆石子,每堆有a[i]个石子,先拿完者败
若不全是单个石子成堆且异或和不为0,或者全是单个石子成堆且共有偶数堆,则先手必胜
#include<bits/stdc++.h> using namespace std; int main() { int T;scanf("%d",&T); while(T--) { int n;scanf("%d",&n); int ans=0; bool flag=false; while(n--) { int t; scanf("%d",&t); ans^=t; if(t>1) flag=true; } if(flag&&!ans || !flag&&ans) puts("Brother"); else puts("John"); } }
//总结:此类博弈一般需要考虑sg函数, 过段时间再填坑。。。。。。
===========================================================================================
Wythoff游戏
有两堆石子,每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取,先拿完者胜
设少的一堆有a个,多的一堆有b个,k=(1+sqrt(5)/2.0,若a==floor((b-a)*k),则先手必败
#include<bits/stdc++.h> using namespace std; int main() { int T,a,b,t; double k=(1+sqrt(5))/2.0; cin>>T; while(T--) { scanf("%d%d",&a,&b); if(a>b) swap(a,b); t=b-a; printf("%c ",a==(int)(t*k)?'B':'A'); } }