想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:有两个人玩游戏,比如有两个堆石头,一个人只能在多的那堆石头里取,并且只能取少的那堆石头里整数倍的石头。给出两堆石头的数量,两人轮流取,谁先取完其中一堆石头则胜利,并且stan先取,要给出胜利人的名字
解题思路:假设一个这样的状态T1=(x,y),并且x>y,
那么状态T2=(x+y,y)可以到达T1,并且两者之间一个为必胜状态,那么另外一个为必败状态
但是,T3=(x+2y,y)既可以到达T1状态,又可以到达T2状态,那么我们可以说T3状态是一个必胜状态,
同理T4=(x+3y,y),...(x+4y,y)等几个状态,也同样可以到达T1与T2状态,那么这些状态也为必胜状态
所以我们说如果满足x>=2y,则为必胜状态
如果是y<x<2y,这种情况,下个状态只能为(x-y,y),为了保证前面一个数大于后面一个数,我们会将两者交换
x不可能小于y,因为前提假设了x>y
如果x==y,或者x=0或者y=0,那么当前取石子的人胜利
#include <iostream> using namespace std; #define max(a,b) (a)>(b)?(a):(b) #define min(a,b) (a)>(b)?(b):(a) typedef int NumberType; class CGame{ private: NumberType *pFirstNumber; NumberType *pLastNumber; bool PlayGame(); public: CGame(); ~CGame(); void SetNumber(int a,int b); bool GetWinPlayer(); }; CGame::CGame(){ pFirstNumber = new NumberType(); pLastNumber = new NumberType(); } CGame::~CGame(){ delete pFirstNumber; delete pLastNumber; } void CGame::SetNumber(NumberType a,NumberType b){ *pFirstNumber = a; *pLastNumber = b; } bool CGame::GetWinPlayer(){ return PlayGame(); } bool CGame::PlayGame(){ bool ans = false; NumberType a=max(*pFirstNumber,*pLastNumber); NumberType b=min(*pFirstNumber,*pLastNumber); while(b>0){ ans = !ans; if(a / b >= 2) break; //a >= (b<<1) ,会出错,有可能溢出了 a -= b; //a不可能大于b的两倍,所以a只能减去一倍的b swap(a, b); } return ans; } int main(){ NumberType a,b; CGame game; while(cin>>a>>b && a || b){ game.SetNumber(a,b); if(game.GetWinPlayer()){ cout<<"Stan wins"<<endl; }else{ cout<<"Ollie wins"<<endl; } } return 0; }