给定一个由N 个整数和一个整数M (初始为1 )组成的数组arr[] ,任务是在两个玩家A和B根据以下规则进行最佳游戏时,找到玩家 A选择的数组元素的最大和:
- 玩家 A开始游戏。
- 每次都可以从数组的开头选择X个元素,其中X包含在[1, 2*M]范围内,由各自的玩家轮流选择。
- 在上述步骤中选择数组元素后,将这些元素从数组中移除,并将M的值更新为X和M的最大值。
- 上述过程将一直持续到所有数组元素都被选中。
例子:
Input: arr[] = {2, 7, 9, 4, 4}
Output: 10
Explanation:
Initially the array is arr[] = {2, 7, 9, 4, 4} and the value of M = 1, Below are the order of ch0osing array elements by both the players:
Player A: The number of elements can be chosen over the range [1, 2*M] i.e., [1, 2]. So, choose element {2} and remove it. Now the array modifies to {7, 9, 4, 4} and the value of M is max(M, X) = max(1, 1) = 1(X is 1).
Player B: The number of elements can be chosen over the range [1, 2*M] i.e., [1, 2]. So, choose element {7, 9} and remove it. Now the array modifies to {4, 4} and the value of M is max(M, X) = max(1, 2) = 2(X is 2).
Player A: The number of elements can be chosen over the range [1, 2*2] i.e., [1, 1]. So, choose element {4, 4} and remove it. Now the array becomes empty.
Therefore, the sum of elements chosen by the Player A is 2 + 4 + 4 = 10.
Input: arr[] = {1}
Output: 1
朴素方法:解决给定问题的最简单方法是使用递归并根据给定规则从一开始为玩家生成所有可能的选择元素组合,并打印为玩家 A获得的选择元素的最大总和。按照以下步骤解决给定的问题:
- 声明一个递归函数,比如recursiveChoosing(arr, start, M) ,它接受参数数组、当前数组的起始索引和M 的初始值,并在此函数执行以下操作:
- 如果start的值大于N ,则返回0 。
- 如果(N – start)的值最多为2*M ,则返回数组元素从索引start 开始的总和,用于玩家的相应分数。
- 将maxSum初始化为0 ,它存储玩家 A选择的数组元素的最大总和。
- 从头开始查找数组元素的总和并将其存储在变量中,例如total 。
- 迭代范围[1, 2*M] ,并执行以下步骤:
- 对于每个元素X ,从开始选择X 个元素并递归调用从剩余的(N – X) 个元素中选择元素。让此调用返回的值存储在maxSum 中。
- 在上述递归调用结束后,将maxSum的值更新为maxSum和(total – maxSum)的最大值。
- 在每次递归调用中返回maxSum的值。
- 完成上述步骤后,打印函数recursiveChoosing(arr, 0, 1)返回的值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Sum of all numbers in the array
// after start index
int sum(int arr[], int start, int N)
{
int sum1 = 0;
for(int i = start; i < N; i++)
{
sum1 += arr[i];
}
return sum1;
}
// Function to find the maximum sum of
// array elements chosen by Player A
// according to the given criteria
int recursiveChoosing(int arr[], int start,
int M, int N)
{
// Corner Case
if (start >= N)
{
return 0;
}
// Check if all the elements can
// be taken
if (N - start <= 2 * M)
{
// If the difference is less than
// or equal to the available
// chances then pick all numbers
return sum(arr, start, N);
}
int psa = 0;
// Sum of all numbers in the array
int total = sum(arr, start, N);
// Explore each element X
// Skipping the k variable as per
// the new updated chance of utility
for(int x = 1; x < 2 * M + 1; x++)
{
// Sum of elements for Player A
int psb = recursiveChoosing(arr, start + x,
max(x, M), N);
// Even chance sum can be obtained
// by subtracting the odd chances
// sum - total and picking up the
// maximum from that
psa = max(psa, total - psb);
}
// Return the maximum sum of odd chances
return psa;
}
// Driver Code
int main()
{
// Given array arr[]
int arr[] = { 2, 7, 9, 4, 4 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function Call
cout << recursiveChoosing(arr, 0, 1, N);
}
// This code is contributed by ipg2016107
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
// Function to find the maximum sum of
// array elements chosen by Player A
// according to the given criteria
static int recursiveChoosing(int arr[], int start,
int M, int N)
{
// Corner Case
if (start >= N)
{
return 0;
}
// Check if all the elements can
// be taken
if (N - start <= 2 * M)
{
// If the difference is less than
// or equal to the available
// chances then pick all numbers
return sum(arr, start);
}
int psa = 0;
// Sum of all numbers in the array
int total = sum(arr, start);
// Explore each element X
// Skipping the k variable as per
// the new updated chance of utility
for(int x = 1; x < 2 * M + 1; x++)
{
// Sum of elements for Player A
int psb = recursiveChoosing(arr, start + x,
Math.max(x, M), N);
// Even chance sum can be obtained
// by subtracting the odd chances
// sum - total and picking up the
// maximum from that
psa = Math.max(psa, total - psb);
}
// Return the maximum sum of odd chances
return psa;
}
// Sum of all numbers in the array after start index
static int sum(int arr[], int start)
{
int sum = 0;
for(int i = start; i < arr.length; i++)
{
sum += arr[i];
}
return sum;
}
// Driver Code
public static void main(String[] args)
{
// Given array arr[]
int arr[] = { 2, 7, 9, 4, 4 };
int N = arr.length;
// Function Call
System.out.print(recursiveChoosing(
arr, 0, 1, N));
}
}
// This code is contributed by Kingash
Python3
# Python program for the above approach
# Function to find the maximum sum of
# array elements chosen by Player A
# according to the given criteria
def recursiveChoosing(arr, start, M):
# Corner Case
if start >= N:
return 0
# Check if all the elements can
# be taken
if N - start <= 2 * M:
# If the difference is less than
# or equal to the available
# chances then pick all numbers
return sum(arr[start:])
psa = 0
# Sum of all numbers in the array
total = sum(arr[start:])
# Explore each element X
# Skipping the k variable as per
# the new updated chance of utility
for x in range(1, 2 * M + 1):
# Sum of elements for Player A
psb = recursiveChoosing(arr,
start + x, max(x, M))
# Even chance sum can be obtained
# by subtracting the odd chances
# sum - total and picking up the
# maximum from that
psa = max(psa, total - psb)
# Return the maximum sum of odd chances
return psa
# Driver Code
# Given array arr[]
arr = [2, 7, 9, 4, 4]
N = len(arr)
# Function Call
print(recursiveChoosing(arr, 0, 1))
C#
// C# program for the above approach
using System;
class GFG{
// Function to find the maximum sum of
// array elements chosen by Player A
// according to the given criteria
static int recursiveChoosing(int[] arr, int start,
int M, int N)
{
// Corner Case
if (start >= N)
{
return 0;
}
// Check if all the elements can
// be taken
if (N - start <= 2 * M)
{
// If the difference is less than
// or equal to the available
// chances then pick all numbers
return sum(arr, start);
}
int psa = 0;
// Sum of all numbers in the array
int total = sum(arr, start);
// Explore each element X
// Skipping the k variable as per
// the new updated chance of utility
for(int x = 1; x < 2 * M + 1; x++)
{
// Sum of elements for Player A
int psb = recursiveChoosing(arr, start + x,
Math.Max(x, M), N);
// Even chance sum can be obtained
// by subtracting the odd chances
// sum - total and picking up the
// maximum from that
psa = Math.Max(psa, total - psb);
}
// Return the maximum sum of odd chances
return psa;
}
// Sum of all numbers in the array after start index
static int sum(int[] arr, int start)
{
int sum = 0;
for(int i = start; i < arr.Length; i++)
{
sum += arr[i];
}
return sum;
}
// Driver Code
public static void Main()
{
// Given array arr[]
int[] arr = { 2, 7, 9, 4, 4 };
int N = arr.Length;
// Function Call
Console.WriteLine(recursiveChoosing(
arr, 0, 1, N));
}
}
// This code is contributed by susmitakundugoaldanga
Javascript
Python3
# Python program for the above approach
# Function to find the maximum sum of
# array elements chosen by Player A
# according to the given criteria
def recursiveChoosing(arr, start, M, dp):
# Store the key
key = (start, M)
# Corner Case
if start >= N:
return 0
# Check if all the elements can
# be taken or not
if N - start <= 2 * M:
# If the difference is less than
# or equal to the available
# chances then pick all numbers
return sum(arr[start:])
psa = 0
# Find the sum of array elements
# over the range [start, N]
total = sum(arr[start:])
# Checking if the current state is
# previously calculated or not
# If yes then return that value
if key in dp:
return dp[key]
# Traverse over the range [1, 2 * M]
for x in range(1, 2 * M + 1):
# Sum of elements for Player A
psb = recursiveChoosing(arr,
start + x, max(x, M), dp)
# Even chance sum can be obtained
# by subtracting the odd chances
# sum - total and picking up the
# maximum from that
psa = max(psa, total - psb)
# Storing the value in dictionary
dp[key] = psa
# Return the maximum sum of odd chances
return dp[key]
# Driver Code
# Given array arr[]
arr = [2, 7, 9, 4, 4]
N = len(arr)
# Stores the precomputed values
dp = {}
# Function Call
print(recursiveChoosing(arr, 0, 1, dp))
10
时间复杂度: O(K*2 N ),其中K超过范围[1, 2*M]
辅助空间: O(N 2 )
高效方法:上述方法也可以通过使用动态规划进行优化,因为它具有重叠子问题和最优子结构,可以在相同的递归调用中进一步存储和使用。
因此,想法是使用字典来存储每个递归调用的状态,以便可以更快地访问已经计算的状态并降低时间复杂度。
下面是上述方法的实现:
蟒蛇3
# Python program for the above approach
# Function to find the maximum sum of
# array elements chosen by Player A
# according to the given criteria
def recursiveChoosing(arr, start, M, dp):
# Store the key
key = (start, M)
# Corner Case
if start >= N:
return 0
# Check if all the elements can
# be taken or not
if N - start <= 2 * M:
# If the difference is less than
# or equal to the available
# chances then pick all numbers
return sum(arr[start:])
psa = 0
# Find the sum of array elements
# over the range [start, N]
total = sum(arr[start:])
# Checking if the current state is
# previously calculated or not
# If yes then return that value
if key in dp:
return dp[key]
# Traverse over the range [1, 2 * M]
for x in range(1, 2 * M + 1):
# Sum of elements for Player A
psb = recursiveChoosing(arr,
start + x, max(x, M), dp)
# Even chance sum can be obtained
# by subtracting the odd chances
# sum - total and picking up the
# maximum from that
psa = max(psa, total - psb)
# Storing the value in dictionary
dp[key] = psa
# Return the maximum sum of odd chances
return dp[key]
# Driver Code
# Given array arr[]
arr = [2, 7, 9, 4, 4]
N = len(arr)
# Stores the precomputed values
dp = {}
# Function Call
print(recursiveChoosing(arr, 0, 1, dp))
10
时间复杂度: O(K*N 2 ),其中K在[1, 2*M]范围内
辅助空间: O(N 2 )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。