📌  相关文章
📜  找出每回合最多从一堆石头中取出 3 个石头的游戏的获胜者

📅  最后修改于: 2021-09-17 16:01:48             🧑  作者: Mango

给定的阵列ARR []的大小N,表示指定到N石头,两个玩家,PLAYER1Player2值,起到交替匝的游戏。在每一回合中,玩家可以从第一批剩余的石头中取出1、23颗石头,并将所有移除的石头的总和添加到玩家的分数中。考虑到两个玩家都玩得最好,任务是打印游戏的赢家。如果双方以相同的分数结束游戏,则打印“Tie”

例子:

朴素的方法:简单的方法是选择可以最大化石头价值总和的石头数量。当两个玩家都以最佳方式玩并且玩家 1 开始游戏时,玩家 1 选择 1 或 2 或 3 颗棋子,并将剩余的棋子传递给下一个玩家。因此,必须从 Player1 的分数中减去 Player2 的分数。这个想法是使用递归来解决问题。令 Player1 的最大分数为res ,这是递归调用后得到的。

  • 如果结果res > 0 ,则 Player1 获胜
  • 如果结果为res < 0 ,则 Player2 获胜
  • 如果结果为res == 0 ,则为平局。

递归树看起来像这样,其中一些子问题重复多次。

请按照以下步骤解决问题:

  • 声明一个递归函数,比如maxScore(i) ,如果游戏从索引i开始,则计算Player1的最大分数
    • 如果i ≥ n的值,则返回0
    • 初始化一个变量,比如score为 INT_MIN,用来存储 Player1 的最大分数
      • 挑选 1 块石头: score = max(score, arr[i] – maxScore(i + 1))
      • 挑选 2 个石头,即(i + 1 < N) : score = max(score, arr[i] + arr[i + 1] – maxScore(i + 2))
      • 选择 3 个石头,即(i + 2 < N) : score = max(score, arr[i] + arr[i + 1] + arr[i + 2] – maxScore(i + 3))
    • 返回score的值。
  • maxScore(0)的值存储在变量res 中
  • 如果解析度> 0的值,则打印“PLAYER1”,如果RES <0,打印“Player2”,否则输出“平局”。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the maximum score of Player1
int maximumStonesUtil(int* arr, int n, int i)
{
    // Base Case
    if (i >= n)
        return 0;
 
    // Variable to store maximum score
    int ans = INT_MIN;
 
    // Pick one stone
    ans = max(ans,
              arr[i] - maximumStonesUtil(arr, n, i + 1));
 
    // Pick 2 stones
    if (i + 1 < n)
        ans = max(ans,
                  arr[i] + arr[i + 1]
                      - maximumStonesUtil(arr, n, i + 2));
 
    // Pick 3 stones
    if (i + 2 < n)
        ans = max(ans,
                  arr[i] + arr[i + 1] + arr[i + 2]
                      - maximumStonesUtil(arr, n, i + 3));
 
    // Return the score of the player
    return ans;
}
 
// Function to find the winner of the game
string maximumStones(int* arr, int n)
{
    // Store the result
    int res = maximumStonesUtil(arr, n, 0);
 
    // Player 1 wins
    if (res > 0)
        return "Player1";
 
    // PLayer 2 wins
    else if (res < 0)
        return "Player2";
 
    // Tie
    else
        return "Tie";
}
 
// Driver Code
int main()
{
    // Given Input
    int arr[] = { 1, 2, 3, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << maximumStones(arr, n);
 
    return 0;
}


Java
// Java program for the above approach
class GFG{
 
// Function to find the maximum score of Player1
static int maximumStonesUtil(int[] arr, int n,
                             int i)
{
     
    // Base Case
    if (i >= n)
        return 0;
 
    // Variable to store maximum score
    int ans = Integer.MIN_VALUE;
 
    // Pick one stone
    ans = Math.max(ans, arr[i] - maximumStonesUtil(
                     arr, n, i + 1));
 
    // Pick 2 stones
    if (i + 1 < n)
        ans = Math.max(ans, arr[i] + arr[i + 1] -
               maximumStonesUtil(arr, n, i + 2));
 
    // Pick 3 stones
    if (i + 2 < n)
        ans = Math.max(
            ans,
            arr[i] + arr[i + 1] + arr[i + 2]
                - maximumStonesUtil(arr, n, i + 3));
 
    // Return the score of the player
    return ans;
}
 
// Function to find the winner of the game
static String maximumStones(int[] arr, int n)
{
     
    // Store the result
    int res = maximumStonesUtil(arr, n, 0);
 
    // Player 1 wins
    if (res > 0)
        return "Player1";
 
    // PLayer 2 wins
    else if (res < 0)
        return "Player2";
 
    // Tie
    else
        return "Tie";
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 7 };
    int n = arr.length;
 
    // Function Call
    System.out.println(maximumStones(arr, n));
}
}
 
// This code is contributed by abhinavjain194


Python3
# Python3 program for the above approach
import sys
 
# Function to find the maximum score of Player1
def maximumStonesUtil(arr, n, i):
     
    # Base Case
    if (i >= n):
        return 0
 
    # Variable to store maximum score
    ans = -sys.maxsize-1;
 
    # Pick one stone
    ans = max(
        ans, arr[i] - maximumStonesUtil(
                       arr, n, i + 1))
 
    # Pick 2 stones
    if (i + 1 < n):
        ans = max(
            ans, arr[i] + arr[i + 1]- maximumStonesUtil(
                      arr, n, i + 2))
 
    # Pick 3 stones
    if (i + 2 < n):
        ans = max(
            ans, arr[i] + arr[i + 1] + arr[i + 2]-
                 maximumStonesUtil(arr, n, i + 3));
 
    # Return the score of the player
    return ans
 
# Function to find the winner of the game
def maximumStones(arr, n):
     
    # Store the result
    res = maximumStonesUtil(arr, n, 0)
 
    # Player 1 wins
    if (res > 0):
        return "Player1"
 
    # PLayer 2 wins
    elif(res < 0):
        return "Player2"
 
    # Tie
    else:
        return "Tie"
 
# Driver Code
if __name__ == '__main__':
     
    # Given Input
    arr = [ 1, 2, 3, 7 ]
    n = len(arr)
 
    # Function Call
    print(maximumStones(arr, n))
 
# This code is contributed by SURENDRA_GANGWAR


C#
// C# program for the above approach
using System;
         
class GFG
{
 
// Function to find the maximum score of Player1
static int maximumStonesUtil(int[] arr, int n,
                             int i)
{
     
    // Base Case
    if (i >= n)
        return 0;
 
    // Variable to store maximum score
    int ans = Int32.MinValue;
 
    // Pick one stone
    ans = Math.Max(ans, arr[i] - maximumStonesUtil(
                     arr, n, i + 1));
 
    // Pick 2 stones
    if (i + 1 < n)
        ans = Math.Max(ans, arr[i] + arr[i + 1] -
               maximumStonesUtil(arr, n, i + 2));
 
    // Pick 3 stones
    if (i + 2 < n)
        ans = Math.Max(
            ans,
            arr[i] + arr[i + 1] + arr[i + 2]
                - maximumStonesUtil(arr, n, i + 3));
 
    // Return the score of the player
    return ans;
}
 
// Function to find the winner of the game
static String maximumStones(int[] arr, int n)
{
     
    // Store the result
    int res = maximumStonesUtil(arr, n, 0);
 
    // Player 1 wins
    if (res > 0)
        return "Player1";
 
    // PLayer 2 wins
    else if (res < 0)
        return "Player2";
 
    // Tie
    else
        return "Tie";
}
     
// Driver Code
public static void Main()
{
    int[] arr = { 1, 2, 3, 7 };
    int n = arr.Length;
 
    // Function Call
    Console.WriteLine(maximumStones(arr, n));
 
}
}
 
// This code is contributed by code_hunt.


Javascript


C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the maximum score of Player 1
int maximumStonesUtil(int* arr, int n, int i,
                      vector& dp)
{
    // Base Case
    if (i >= n)
        return 0;
 
    int& ans = dp[i];
 
    // If the result is already computed, then
    // return the result
    if (ans != -1)
        return ans;
 
    // Variable to store maximum score
    ans = INT_MIN;
 
    // Pick one stone
    ans = max(
        ans, arr[i] - maximumStonesUtil(arr, n, i + 1, dp));
 
    // Pick 2 stones
    if (i + 1 < n)
        ans = max(ans, arr[i] + arr[i + 1]
                           - maximumStonesUtil(arr, n,
                                               i + 2, dp));
 
    // Pick 3 stones
    if (i + 2 < n)
        ans = max(ans, arr[i] + arr[i + 1] + arr[i + 2]
                           - maximumStonesUtil(arr, n,
                                               i + 3, dp));
 
    // Return the score of the player
    return ans;
}
 
// Function to find the winner of the game
string maximumStones(int* arr, int n)
{
    // Create a 1D table, dp of size N
    vector dp(n, -1);
 
    // Store the result
    int res = maximumStonesUtil(arr, n, 0, dp);
 
    // Player 1 wins
    if (res > 0)
        return "Player1";
 
    // PLayer 2 wins
    else if (res < 0)
        return "Player2";
 
    // Tie
    else
        return "Tie";
}
 
// Driver Code
int main()
{
    // Given Input
    int arr[] = { 1, 2, 3, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << maximumStones(arr, n);
 
    return 0;
}


输出:
Player2

时间复杂度: O(3 N )
辅助空间: O(N)

高效的方法:为了优化上述方法,思想是使用动态规划。给定的问题具有最优子结构属性和重叠子问题。通过创建一个大小为N 的dp的一维表来使用记忆化来存储递归调用的结果。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the maximum score of Player 1
int maximumStonesUtil(int* arr, int n, int i,
                      vector& dp)
{
    // Base Case
    if (i >= n)
        return 0;
 
    int& ans = dp[i];
 
    // If the result is already computed, then
    // return the result
    if (ans != -1)
        return ans;
 
    // Variable to store maximum score
    ans = INT_MIN;
 
    // Pick one stone
    ans = max(
        ans, arr[i] - maximumStonesUtil(arr, n, i + 1, dp));
 
    // Pick 2 stones
    if (i + 1 < n)
        ans = max(ans, arr[i] + arr[i + 1]
                           - maximumStonesUtil(arr, n,
                                               i + 2, dp));
 
    // Pick 3 stones
    if (i + 2 < n)
        ans = max(ans, arr[i] + arr[i + 1] + arr[i + 2]
                           - maximumStonesUtil(arr, n,
                                               i + 3, dp));
 
    // Return the score of the player
    return ans;
}
 
// Function to find the winner of the game
string maximumStones(int* arr, int n)
{
    // Create a 1D table, dp of size N
    vector dp(n, -1);
 
    // Store the result
    int res = maximumStonesUtil(arr, n, 0, dp);
 
    // Player 1 wins
    if (res > 0)
        return "Player1";
 
    // PLayer 2 wins
    else if (res < 0)
        return "Player2";
 
    // Tie
    else
        return "Tie";
}
 
// Driver Code
int main()
{
    // Given Input
    int arr[] = { 1, 2, 3, 7 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << maximumStones(arr, n);
 
    return 0;
}
输出:
Player2

时间复杂度: O(N)
辅助空间: O(N)