問題描述
兩個人玩取球的遊戲。
一共有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;
}