博弈题集(1)
来源:互联网 发布:nfc手机读写软件 编辑:程序博客网 时间:2024/05/01 18:42
题目:看到 这里 的一个分类,打算分四次把它搞定吧,现在看第一部分的题:
//HDOJ1079 Calendar Game
具体情况具体分析就好,这题数据蛮弱,之前写错了也过了。
#include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> using namespace std; int main() { int t,y,m,d,tmp; bool tag; scanf("%d",&t); while(t--) { tag=false;; scanf("%d%d%d",&y,&m,&d); tmp=m+d; if(y==2001 && m==11 && d==4) tag=false; else if((m==1||m==3||m==5||m==7)&&d==31) // 8.31 10.31 和 12.31 果断抛弃 tag=true; else if((m==4||m==6||m==9||m==11)&&d==30) //后续可选择为奇态 tag=true; // 对于2.28的不管是不是闰年,后续可以是3.28为奇态 else if(tmp%2==0) tag=true; if(tag) printf("YES\n"); else printf("NO\n"); } return 0; }
//HDOJ1525&POJ2348 Euclid's Game
watashi翻译的那本书上有讲过,考虑一下没有选择的时候就快接近答案了。
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>using namespace std;bool win;void solve(int a,int b){ if(a>b) swap(a,b); if(b%a==0 || b/a>1) return ; win=!win; b=b%a; solve(a,b);}int main(){ int a,b; while(scanf("%d%d",&a,&b),a+b) { win=1; solve(a,b); if(win) printf("Stan wins\n"); else printf("Ollie wins\n"); } return 0;}
//HDOJ1564 Play a game
水题
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>using namespace std;int main(){ int n; while(scanf("%d",&n)!=EOF,n) { if(n&1) printf("ailyanlu\n"); else printf("8600\n"); } return 0;}
//HDOJ1846 Brave Game
简单巴什博弈
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>using namespace std;int main(){ int t; scanf("%d",&t); int n,m; while(t--) { scanf("%d%d",&n,&m); if(n%(m+1)) printf("first\n"); else printf("second\n"); } return 0;}
//HDOJ1847 Good Luck in CET-4 Everybody!
枚举一下必败态和必胜态,或者用sg函数也可以解释
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>#include <set>using namespace std;set<int>s;int main(){ s.clear(); int two=1; for(;two<=1000;two*=2) s.insert(two); for(int i=1;i<=1000;i++) { if(s.count(i)) continue; for(set<int>::iterator it=s.begin();it!=s.end();it++) { if(*it+i<=1000) s.insert(*it+i); } } int n; while(scanf("%d",&n)!=EOF) { if(s.count(n)) printf("Kiki\n"); else printf("Cici\n"); } return 0;}
//HDOJ2147 kiki's game
跟圆桌那个差不多,取中心,然后跟着对手取对称的。
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>#include <set>using namespace std;int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF,m+n) { if((n&1)&&(m&1)) printf("What a pity!\n"); else printf("Wonderful!\n"); } return 0;}
//HDOJ2516
简单sg函数
#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <vector>#include <set>using namespace std;set<int>s;int main(){ s.clear(); int x=1,y=1,tmp=x+y; while(tmp>0) { s.insert(tmp); x=y; y=tmp; tmp=x+y; } int n; while(scanf("%d",&n),n) { if(s.count(n)) printf("Second win\n"); else printf("First win\n"); } return 0;}
//HDOJ2897
sg打表找规律,或者理解成巴什博弈
#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#include <set>using namespace std;int main(){ int n,p,q; while(scanf("%d%d%d",&n,&p,&q)!=EOF) { int tmp=n%(p+q); if(tmp==0 || tmp>p) printf("WIN\n"); else printf("LOST\n"); } return 0;}
//HDOJ3032 Nim or not Nim?
sg打表
// SG博弈/*#include <cstring>#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>#include <set>using namespace std;#define maxn 2000set<int>s;int sg[maxn];int solve(){ int i=0; while(s.count(i)) i++; return i;}int main(){ int n; scanf("%d",&n); sg[0]=0; for(int i=0;i<=n;i++) { s.clear(); for(int j=0;j<i;j++) { s.insert(sg[j]); s.insert(sg[j]^sg[i-j]); } sg[i]=solve(); } for(int i=1;i<=n;i++) cout<<i<<":"<<sg[i]<<endl;}*/#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>using namespace std;int sg(int n){ if(n%4==0) return n-1; if(n%4==3) return n+1; return n;}int main(){ int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int ans=0,x; for(int i=0;i<n;i++) { scanf("%d",&x); ans^=sg(x); } if(ans) printf("Alice\n"); else printf("Bob\n"); } return 0;}
//HDOJ3389 Game
1,3,4是不能够移动的终点。
// 打表找出最终不可移动的点// 找出移动到不可移动点的编号的规律,转化成nim/*#include <cstring>#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>#include <set>using namespace std;#define maxn 60int st[maxn];int main(){ memset(st,0,sizeof(st)); for(int i=1;i<maxn;i++) for(int j=i+1;j<maxn;j++) if((i+j)%3==0 && ((i+j)/3)&1 ) st[j]=1; printf("输出不能移动的位置:\n"); for(int i=1;i<maxn;i++) if(st[i]==0) // 输出不能移动的位置 cout<<i<<" "; puts(""); printf("可以移动的:\n"); for(int i=1;i<maxn;i++) for(int j=i+1;j<maxn;j++) if((i+j)%3==0 && ((i+j)/3)&1 ) cout<<i<<" <- "<<j<<endl; return 0;}*/// 发现对于能一次到达1,3,4状态的编号都是mod6的数#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int main(){ int t; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { int n,x; scanf("%d",&n); int ans=0; for(int i=1;i<=n;i++) { scanf("%d",&x); if(i%6==2 || i%6==0 || i%6==5) ans^=x; } printf("Case %d: ",cas); if(ans) printf("Alice\n"); else printf("Bob\n"); } return 0;}
//HDOJ3537 Daizhenyang's Coin
MT博弈
// Mock Turtles// http://blog.sina.com.cn/s/blog_8f06da99010125ol.html// http://blog.csdn.net/acm_cxlove/article/details/7854181#include <cstring>#include <cmath>#include <iostream>#include <algorithm>#include <cstdio>#include <set>using namespace std;set<long long>s;int main(){ int n; while(scanf("%d",&n)!=EOF) { s.clear(); long long ans=0; long long x; for(int i=0;i<n;i++) { scanf("%I64d",&x); s.insert(x); } set<long long>::iterator it=s.begin(); for(;it!=s.end();it++) { if(__builtin_popcount(2* *it)&1) ans^=2* *it; else ans^=2* *it+1; } if(ans) printf("No\n"); else printf("Yes\n"); }}
//HDOJ3544 Alice's Game
策略:每次尽量均分
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#include <map>using namespace std;int main(){ int t; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { int n; scanf("%d",&n); long long ansx=0,ansy=0,x,y; while(n--) { scanf("%I64d%I64d",&x,&y); while(x>1 && y>1) { x/=2; y/=2; } if(x==1) ansy+=y-1; if(y==1) ansx+=x-1; } printf("Case %d: ",cas); if(ansx>ansy) printf("Alice\n"); else printf("Bob\n"); } return 0;}
//HDOJ3863 No Gambling
永远必胜
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#include <map>using namespace std;int main(){ int n; while(scanf("%d",&n),n!=-1) { printf("I bet on Oregon Maple~\n"); } return 0;}
//HDOJ3951 Coin Game
一个硬币的时候判奇偶,两个及以上硬币的时候转化成跟watashi翻译那本书上那个博弈一样,第一次不管对手怎么拿,我们都可以转化成相同的两条链,然后跟对手一样对称的拿。
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int a[100];int main(){ int t; int n,k; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { scanf("%d%d",&n,&k); printf("Case %d: ",cas); if(k==1) { if(n&1) printf("first\n"); else printf("second\n"); continue; } if(n-k<=0) printf("first\n"); else printf("second\n"); } return 0;}
//HDOJ2188 悼念512汶川大地震遇难同胞——选拔志愿者
简单巴什博弈
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int main(){ int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); if(n%(m+1)==0) printf("Rabbit\n"); else printf("Grass\n"); } return 0;}
//HDOJ2149 Public Sale
巴什博弈第一步取法
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n%(m+1)==0) printf("none\n"); else { if(n/(m+1)==0) { for(int i=n;i<m;i++) printf("%d ",i); printf("%d\n",m); } else { printf("%d\n",n%(m+1)); } } } return 0;}
//HDOJ1850 Being a Good Boy in Spring Festival
nim博弈取法
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int a[100];int main(){ int n,x; while(scanf("%d",&n),n) { int ans=0,hah=0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); ans^=a[i]; } for(int i=0;i<n;i++) { if((ans^a[i])<a[i]) // 表明一开始选这个可以将ans二进制中某个1变成0 hah++; } printf("%d\n",hah); } return 0;}
//HDOJ2176 取(m堆)石子游戏
nim博弈取法
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;int a[200001];int main(){ int n; while(scanf("%d",&n)!=EOF,n) { int ans=0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); ans^=a[i]; } if(ans==0) { printf("No\n"); continue; } printf("Yes\n"); for(int i=0;i<n;i++) { if((ans^a[i])<a[i]) printf("%d %d\n",a[i],ans^a[i]); } } return 0;}
//HDOJ1527&POJ1067 取石子游戏
简单威佐夫博弈
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>using namespace std;double tmp=(sqrt(5.0)+1)/2;int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n>m) swap(n,m); if(int((m-n)*tmp)==n) printf("0\n"); else printf("1\n"); } return 0;}
//HDOJ2177 取(2堆)石子游戏
威佐夫博弈第一步取法
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#include <map>using namespace std;double tmp=(sqrt(5.0)+1)/2;map<int,int>mp;map<int,int>ans;int main(){ mp.clear(); for(int i=0;i<1000010;i++) mp[(int)i*tmp]=(int)i*tmp+i; map<int,int>::iterator it=mp.begin(); int n,m; while(scanf("%d%d",&n,&m)!=EOF,m+n) { ans.clear(); if(mp[n]==m) printf("0\n"); else { printf("1\n"); map<int,int>::iterator it=mp.begin(),ii=mp.end(),jj=mp.end(); for(;it!=mp.end() && (it->first<=m);it++) { if(it->second==m) { ii=it; } else if(it->second==n) { jj=it; } if(n-it->first == m-it->second && m-it->second>0) ans[it->first]=it->second; } for(it=ans.begin();it!=ans.end();it++) { printf("%d %d\n",it->first,it->second); } if(mp[n]&&mp[n]<m) printf("%d %d\n",n,mp[n]); if(ii!=mp.end()&&ii->first<n) printf("%d %d\n",ii->first,m); if(jj!=mp.end()) printf("%d %d\n",jj->first,jj->second); } } return 0;}
//HDOJ1517&POJ2505 A Multiplication Game
假设当前状态时必败态,然后一直往前推,能够到达必败态的是必胜态,只能到达必胜态的是必败态,枚举一下区间即可。
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#include <map>using namespace std;int main(){ long long n; while(scanf("%I64d",&n)!=EOF) { bool ans=0; while(n>1) { if(!ans) n=(n-1)/9+1; else n=(n-1)/2+1; ans^=1; } if(ans) printf("Stan wins.\n"); else printf("Ollie wins.\n"); } return 0;}
//HDOJ2486&HDOJ2580&POJ3922 A simple stone game
K倍动态减法博弈,具体证明看论文吧。
#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>using namespace std;const int maxn = 1000010 ;int a[maxn],b[maxn];int n,k;int solve(int n){ int i=0,j=0; a[0]=1,b[0]=1; while(a[i]<n) { // a[i]表示当前能用来构造的最大项 // b[i]表示由0...i,由a中数列所构成的最大值 i++; a[i]=b[i-1]+1; // b[i-1]+1不能表示成a中的前i-1中某不连续几项的和,故需要构造 while(a[j+1]*k<a[i]) j++; // 找到最近的恰好与第i项差值在k倍以上的 if(a[j]*k<a[i]) b[i]=b[j]+a[i]; //用到了a中前i-2项,保证和为a中某不连续的话,可以取当前的j else // 倒数第二项和最后一项差值恰好为k倍时,能构造的最大项不变 b[i]=a[i]; } if(n==a[i]) return -1; int ans; while(n) { if(n>=a[i]) n-=a[i],ans=a[i]; i--; } return ans;}int main(){ int t; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { scanf("%d%d",&n,&k); int ans = solve(n); printf("Case %d: ",cas); if(ans==-1) printf("lose\n"); else printf("%d\n",ans); } return 0;}
//HDOJ4315 Climbing the Hill
转化一下,类似于watashi翻译那本书上的一个nim博弈,好像正规叫法是阶梯博弈,特殊情况就是要讨论一下,k=1和k=2的情况,具体见代码
#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <iostream>#include <vector>#include <map>using namespace std;int a[1010];int main(){ int n,k; while(scanf("%d%d",&n,&k)!=EOF) { int ans=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } if(k==1) { printf("Alice\n"); continue; } if(n&1) { ans^=a[1]-(k==2); for(int i=2;i<n;i+=2) ans^=(a[i+1]-a[i]-1); } else { for(int i=1;i<=n;i+=2) ans^=(a[i+1]-a[i]-1); } if(ans) printf("Alice\n"); else printf("Bob\n"); } return 0;}
最后两道没来及学新知识,周末过了稍微闲点的时候再补上。
HDOJ1538 A Puzzle for Pirates [海盗分金问题]
HDOJ3404 Switch lights [Nim积]
- 博弈题集(1)
- 博弈题集
- 博弈题集
- 博弈题集
- 博弈题集
- 博弈题集
- 博弈题集
- 博弈概率题(1)
- 博弈1
- 博弈1
- 博弈-1
- 博弈问题之其它博弈合集
- 博弈类题目集
- 博弈题 poj 1143
- 博弈题方法
- 简单博弈题
- 博弈题算法小结
- hdoj博弈基础题
- 开源代码网站收集
- mysql5.6 1067问题
- 10.3.6 TCP传输连接建立
- xml文件格式
- SAN存储系统构架解析
- 博弈题集(1)
- ECMAScrip的forEach
- 成员函数末尾使用const关键字
- 10.3.6 TCP传输连接建立
- 导入工程,添加jar包之后还是报错?
- with语句的使用
- 计算机网络
- 在WIN7平台下搭建Ruby On Rails web开发环境
- 查看哪些列上建了索引