藍橋杯---取球博弈---DFS+記憶化---C++

問題描述

兩個人玩取球的遊戲。
一共有N個球,每人輪流取球,每次可取集合{n1,n2,n3}中的任何一個數目。
如果無法繼續取球,則遊戲結束。
此時,持有奇數個球的一方獲勝。
如果兩人都是奇數,則爲平局。
假設雙方都採用最聰明的取法,
第一個取球的人一定能贏嗎?
試編程解決這個問題。

輸入
第一行3個正整數n1 n2 n3,空格分開,表示每次可取的數目 (0<n1,n2,n3<100)
第二行5個正整數x1 x2 … x5,空格分開,表示5局的初始球數(0<xi<1000)

輸出
一行5個字符,空格分開。分別表示每局先取球的人能否獲勝。
能獲勝則輸出+,
次之,如有辦法逼平對手,輸出0,
無論如何都會輸,則輸出 -

輸入例子 1

1 2 3
1 2 3 4 5

輸出例子 1

+ 0 + 0 -

輸入例子 2

1 4 5
10 11 12 13 15

輸出例子 2

0 - 0 + +

輸入例子 3

2 3 5

輸出例子 3

7 8 9 10 11
+ 0 0 0 0

提示
峯值內存消耗(含虛擬機) < 256M
CPU消耗 < 3000ms

實現思路

深搜 + 記憶化, 每個人都是最優解 = 優先考慮贏的情況, 其次考慮平的情況, 再其次纔是輸。

實現代碼

#include<iostream>
#include<algorithm>
using namespace std;

const int SIZE = 1e3 + 5;

int dp[SIZE][2][2];
int a[3];

int dfs(int now, int nowplayer, int otherplayer) {
	if (dp[now][nowplayer][otherplayer]) {
		return dp[now][nowplayer][otherplayer];
	}

	if (now < a[0]) {
		if ((nowplayer & 1) == (otherplayer & 1)) return -1;	//平
		if (nowplayer & 1) return 1;							//勝
		return 2;												//負
	}

	else {
		bool noplayerwin = false;
		for (int i = 2; i >= 0; i--) {
			if (a[i] > now) continue;
			else {
				int otherresult = dfs(now - a[i], otherplayer, (nowplayer + a[i]) & 1);
				if (otherresult == 2) return dp[now][nowplayer][otherplayer] = 1;
				if (otherresult == -1) noplayerwin = true;
			}
		}
		if (noplayerwin) return dp[now][nowplayer][otherplayer] = -1;
		return dp[now][nowplayer][otherplayer] = 2;
	}
}


int main() {
	int maxnum;
	memset(dp, 0, sizeof(dp));
	cin >> a[0] >> a[1] >> a[2];
	sort(a, a + 3);
	for (int i = 1; i <= 5; i++) {
		cin >> maxnum;
		switch (dfs(maxnum, 0, 0))
		{
		case  1: cout << "+ "; break;
		case  2: cout << "- "; break;
		case -1: cout << "0 "; break;
		}
	}
	return 0;
}
發佈了117 篇原創文章 · 獲贊 19 · 訪問量 6822
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章