資訊學奧賽一本通 1218:取石子游戲(NIM)

everwide1982發表於2020-10-17

【題目描述】
有兩堆石子,兩個人輪流去取。每次取的時候,只能從較多的那堆石子裡取,並且取的數目必須是較少的那堆石子數目的整數倍,最後誰能夠把一堆石子取空誰就算贏。

比如初始的時候兩堆石子的數目是25和7。

25 7 --> 11 7 --> 4 7 --> 4 3 --> 1 3 --> 1 0
選手1取 選手2取 選手1取 選手2取 選手1取
最後選手1(先取的)獲勝,在取的過程中選手2都只有唯一的一種取法。

給定初始時石子的數目,如果兩個人都採取最優策略,請問先手能否獲勝。

【輸入】
輸入包含多數資料。每組資料一行,包含兩個正整數a和b,表示初始時石子的數目。

輸入以兩個0表示結束。

【輸出】
如果先手勝,輸出"win",否則輸出"lose"。

【輸入樣例】
34 12
15 24
0 0
【輸出樣例】
win
lose
【提示】
假設石子數目為(a,b)且a >= b,如果[a/b] >= 2則先手必勝,如果[a/b]<2,那麼先手只有唯一的一種取法。[a/b]表示a除以b取整後的值。
【心得】使用變數標記先後手即可。
【AC程式碼】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
bool dfs(int a,int b,bool flag)
{
	if(a>=2*b||a%b==0) return flag;
	else return dfs(b,a-b,!flag);
}
int main()
{
	int a,b;
	while(scanf("%d %d",&a,&b)==2)
	{
		if(a==0&&b==0) break;
		if(a<b) swap(a,b);
		if(dfs(a,b,true)) cout<<"win"<<endl;
		else cout<<"lose"<<endl;
	}
	return 0;
}

相關文章