📜  修改游戏的最佳策略

📅  最后修改于: 2021-04-24 18:45:39             🧑  作者: Mango

问题陈述:考虑一行n个硬币,值v1。 。 。 vn,其中n为偶数。我们通过交替轮流与对手进行比赛。在每一回合中,玩家执行以下操作K次

玩家从该行中选择第一个或最后一个硬币,将其从该行中永久删除,并接收该硬币的价值。

确定如果用户先移动,则用户肯定可以赢得的最大可能金额。

注意:对手和用户一样聪明。

例子:

方法:
需要形成一个递归解决方案,并且需要存储子问题的值以计算结果。
以一个例子来得出递归解;

arr = {10,15,20,9,2,5},k = 2
因此,如果用户在第一轮中选择10、15,则数组中将剩下20、9、2、5。
但是,如果用户选择10、5;然后将15、20、9、2留在数组中。
最后,如果用户选择5、2;然后将10、15、20、9留在数组中。

因此,在选择k个元素之后的任何迭代中,将保留长度为nk的连续子数组以用于下一次计算。

因此,可以在以下位置形成递归解决方案:

所选元素的总和Sc =(sum(l,r)– sum(l + i,l + i + nk-1))
现在,对手将执行下一回合,因此
下一步中选择的元素总数=当前数组从l到r的总和–
对手在下一步骤中选择的元素总和等于

Nc=(sum(l+i, l+i+n-k-1) - S(l+i, l+i+n-k-1)).
S(l, r) = Sc + Nc
where,
Nc=(sum(l+i, l+i+n-k-1) - S(l+i, l+i+n-k-1))
Sc=(sum(l, r) - sum(l+i, l+i+n-k-1))

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
#define ll long long int
  
// Function to return sum of subarray from l to r
ll sum(int arr[], int l, int r)
{
    // calculate sum by a loop from l to r
    ll s = 0;
    for (int i = l; i <= r; i++) {
        s += arr[i];
    }
    return s;
}
  
// dp to store the values of sub problems
ll dp[101][101][101] = { 0 };
  
ll solve(int arr[], int l, int r, int k)
{
    // if length of the array is less than k
    // return the sum
    if (r - l + 1 <= k)
        return sum(arr, l, r);
  
    // if the value is previously calculated
    if (dp[l][r][k])
        return dp[l][r][k];
  
    // else calculate the value
    ll sum_ = sum(arr, l, r);
    ll len_r = (r - l + 1) - k;
    ll len = (r - l + 1);
    ll ans = 0;
  
    // select all the sub array of length len_r
    for (int i = 0; i < len - len_r + 1; i++) {
        // get the sum of that sub array
        ll sum_sub = sum(arr, i + l, i + l + len_r - 1);
  
        // check if it is the maximum or not
        ans = max(ans, (sum_ - sum_sub) + (sum_sub - 
                  solve(arr, i + l, i + l + len_r - 1, k)));
    }
  
    // store it in the table
    dp[l][r][k] = ans;
  
    return ans;
}
  
// Driver code
int main()
{
    int arr[] = { 10, 15, 20, 9, 2, 5 }, k = 2;
    int n = sizeof(arr) / sizeof(int);
    memset(dp, 0, sizeof(dp));
  
    cout << solve(arr, 0, n - 1, k);
  
    return 0;
}


Java
// Java implementation of the above approach 
class GFG
{
      
    // Function to return sum of subarray from l to r 
    static int sum(int arr[], int l, int r) 
    { 
        // calculate sum by a loop from l to r 
        int s = 0; 
        for (int i = l; i <= r; i++)
        { 
            s += arr[i]; 
        } 
        return s; 
    } 
      
    // dp to store the values of sub problems 
    static int dp[][][] = new int[101][101][101] ; 
      
    static int solve(int arr[], int l, int r, int k) 
    { 
        // if length of the array is less than k 
        // return the sum 
        if (r - l + 1 <= k) 
            return sum(arr, l, r); 
      
        // if the value is previously calculated 
        if (dp[l][r][k] != 0) 
            return dp[l][r][k]; 
      
        // else calculate the value 
        int sum_ = sum(arr, l, r); 
        int len_r = (r - l + 1) - k; 
        int len = (r - l + 1); 
        int ans = 0; 
      
        // select all the sub array of length len_r 
        for (int i = 0; i < len - len_r + 1; i++) 
        { 
            // get the sum of that sub array 
            int sum_sub = sum(arr, i + l, i + l + len_r - 1); 
      
            // check if it is the maximum or not 
            ans = Math.max(ans, (sum_ - sum_sub) + (sum_sub - 
                    solve(arr, i + l, i + l + len_r - 1, k))); 
        } 
      
        // store it in the table 
        dp[l][r][k] = ans; 
      
        return ans; 
    } 
      
    // Driver code 
    public static void main (String[] args) 
    {
      
        int arr[] = { 10, 15, 20, 9, 2, 5 }, k = 2; 
        int n = arr.length; 
  
        System.out.println(solve(arr, 0, n - 1, k)); 
      
    }
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation of the above approach 
import numpy as np
  
# Function to return sum of subarray from l to r 
def Sum(arr, l, r) : 
  
    # calculate sum by a loop from l to r 
    s = 0; 
    for i in range(l, r + 1) :
        s += arr[i]; 
  
    return s; 
  
# dp to store the values of sub problems 
dp = np.zeros((101, 101, 101)); 
  
def solve(arr, l, r, k) :
  
    # if length of the array is less than k 
    # return the sum 
    if (r - l + 1 <= k) :
        return Sum(arr, l, r); 
  
    # if the value is previously calculated 
    if (dp[l][r][k]) :
        return dp[l][r][k]; 
  
    # else calculate the value 
    sum_ = Sum(arr, l, r); 
    len_r = (r - l + 1) - k; 
    length = (r - l + 1); 
    ans = 0; 
  
    # select all the sub array of length len_r 
    for i in range(length - len_r + 1) :
          
        # get the sum of that sub array 
        sum_sub = Sum(arr, i + l, i + l + len_r - 1); 
  
        # check if it is the maximum or not 
        ans = max(ans, (sum_ - sum_sub) + (sum_sub -
                            solve(arr, i + l, i + l + len_r - 1, k))); 
  
    # store it in the table 
    dp[l][r][k] = ans; 
  
    return ans; 
  
  
# Driver code 
if __name__ == "__main__" : 
  
    arr = [ 10, 15, 20, 9, 2, 5 ]; k = 2; 
      
    n = len(arr); 
  
    print(solve(arr, 0, n - 1, k)); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the above approach 
using System;
  
class GFG
{
      
    // Function to return sum of subarray from l to r 
    static int sum(int []arr, int l, int r) 
    { 
        // calculate sum by a loop from l to r 
        int s = 0; 
        for (int i = l; i <= r; i++)
        { 
            s += arr[i]; 
        } 
        return s; 
    } 
      
    // dp to store the values of sub problems 
    static int [,,]dp = new int[101, 101, 101] ; 
      
    static int solve(int []arr, int l, int r, int k) 
    { 
        // if length of the array is less than k 
        // return the sum 
        if (r - l + 1 <= k) 
            return sum(arr, l, r); 
      
        // if the value is previously calculated 
        if (dp[l, r, k] != 0) 
            return dp[l, r, k]; 
      
        // else calculate the value 
        int sum_ = sum(arr, l, r); 
        int len_r = (r - l + 1) - k; 
        int len = (r - l + 1); 
        int ans = 0; 
      
        // select all the sub array of length len_r 
        for (int i = 0; i < len - len_r + 1; i++) 
        { 
            // get the sum of that sub array 
            int sum_sub = sum(arr, i + l, i + l + len_r - 1); 
      
            // check if it is the maximum or not 
            ans = Math.Max(ans, (sum_ - sum_sub) + (sum_sub - 
                    solve(arr, i + l, i + l + len_r - 1, k))); 
        } 
      
        // store it in the table 
        dp[l, r, k] = ans; 
      
        return ans; 
    } 
      
    // Driver code 
    public static void Main () 
    {
        int []arr = { 10, 15, 20, 9, 2, 5 };
        int k = 2; 
        int n = arr.Length; 
  
        Console.WriteLine(solve(arr, 0, n - 1, k)); 
    }
}
  
// This code is contributed by AnkitRai01


输出:
32