【提高组】
*我真的是搞不懂博弈论要怎么想*
P1199 三国游戏 (智商)
人的选择是每一行第二大中最大的组合,因为每行第一大一定会被计算机选。
保证计算机的选择结果小于人的结果,∵人可以把计算机最大的组合中的另一个数抢掉,而计算机不可能自动选到最大,否则人选择的就不是最大了(理解一下)。
故人必胜,且最大的组合结果是每行第二大中的最大。
博弈论可以存在每次都必胜的结果别被题面&输出要求骗了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) using namespace std; const int M=505; int n,a[M][M]; int main(){ scanf("%d",&n); For(i,1,n-1){ For(j,i+1,n){ scanf("%d",&a[i][j]); a[j][i]=a[i][j]; } } int ans=0; For(i,1,n){ sort(a[i]+1,a[i]+n+1); ans=ans>a[i][n-1]?ans:a[i][n-1]; } printf("1\n%d\n",ans); return 0; }
P1288 取数游戏II (智商)
*恕我直言Linux真的搞人*
经分析,先手决定游戏方向,先手开局位于a[n]与a[1]间,两种情况下必胜:
1. a[1]边即顺时针方向的第一条边不为0,从第一条边顺时针走碰到为0的边所经边数为偶
2. a[1]边即逆时针方向的第一条边不为0,从(逆时针走)第一条边顺时针走碰到为0的边所经边数为偶
若不是这两种情况中任何一种则必败。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) #define Dfor(i,r,l) for(int i=r;i>=l;i--) using namespace std; const int M=25; int n,a[M]; inline int read(){ int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } int main(){ n=read(); For(i,1,n) a[i]=read(); if(a[1]){ For(i,1,n){ if(!a[i]){ if(!(i&1)){printf("YES\n");return 0;} break; } } } if(a[n]){ Dfor(i,n,1){ if(!a[i]){ if(!((n-i+1)&1)){printf("YES\n");return 0;} break; } } } printf("NO\n"); return 0; }
P1290 欧几里德的游戏(智商)
假设y>x,有以下几种情况:
1. y==x或y为x倍数 先手胜
2. y=kx+b
(1) k>2,则(x,kx+b)一定能转移为(x,x+b)-> (x,b),故当前操作者胜
(2) k<2,则可转移为(y-x,x),递归求胜者
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int c,x,y; bool f(int x,int y,int p){ if(x==y||y>=2*x||!(y%x)) return p; else return f(y-x,x,p^1); } int main(){ cin>>c; while(c--){ cin>>x>>y; if(x>y) swap(x,y); if(!f(x,y,0)) cout<<"Stan wins"<<endl; else cout<<"Ollie wins"<<endl; } return 0; }
P1247 取火柴游戏(智商)
https://www.luogu.org/blog/user53167/solution-p1247
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> int n,a[500005],check; using namespace std; int main(){ scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]),check^=a[i]; if(!check){printf("lose\n");return 0;} for(int i=1; i<=n; i++){ if((check^a[i])<a[i]){ printf("%d %d\n",a[i]-(check^a[i]),i); for(int j=1; j<=n; j++){ if(j!=i) printf("%d ",a[j]); else printf("%d ",check^a[i]); } break; } } return 0; }