poj2348 - Euclid's Game

15 篇文章 0 订阅

                                  想看更多的解题报告: 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;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值