最大选择数组的第一个或最后一个元素

Max chosen of first or last elements of array

你能帮我解决这个问题吗::((

给定一个数组 A[] 有 n 个正数 (n<=5000)。彼得和艾玛玩一个选择数字的游戏。当轮到每个人时,他们可以选择数组的第一个或最后一个元素,然后增加 his/her 分数并将该元素从数组中删除。彼得先上场。

你必须找到谁能赢以及他们的分数,彼得和艾玛都是最好的球员

示例:

A = {4,5,1,3}

第一轮,彼得可以选择第一个数字(4)或最后一个数字(3),所以他选择3然后将其删除。

// A={4,5,1}

在第二轮,Emma 可以选择第一个数字 (4) 或最后一个数字 (1),所以她选择 4 然后将其删除。

// A={5,1}

第三轮,彼得可以选择第一个数字(5)或最后一个数字(1),所以他选择5然后将其删除。

// A={1}

最后一回合,Emma只选了1个号码(1),然后去掉1

现在数组为空所以游戏结束,Peter有3+5=8的分数;艾玛有4+1=5分。所以彼得赢了。

解释为什么彼得没有9分(4+5)而艾玛没有4分(1+3)。因为他们都是最好的玩家,所以当彼得去掉数字 3 时,艾玛会选择 4 而不是 1\

我用过回溯但时间有限

基本思路如下:

让我们称 score(first, right) 一个玩家在剩余元素从 firstlast 元素中可以获得的最好分数。

然后,如果玩家A select first元素,那么玩家B将获得score(first+1, last),并且 然后玩家 A 将获得 sum - player B score.

如果玩家 A select 最后一个元素,则使用相同的逻辑:玩家 B 将获得 score(first, last-1)

这可以很容易地以递归方式实现。

必须实现记忆化以避免重复相同的计算。

复杂度:O(N^2)。

#include <iostream>
#include <vector>
#include <numeric>
#include <tuple>

int sum;
int sum_left;
std::vector<std::vector<int>> mem;

int score_rec (const std::vector<int> &A, int first, int last) {
    if (mem[first][last] >= 0) return mem[first][last];

    sum_left -= A[first];
    int score1 = A[first] + sum_left - score_rec (A, first + 1, last);
    sum_left += A[first];
    
    sum_left -= A[last];
    int score2 = A[last] + sum_left - score_rec (A, first, last - 1);
    sum_left += A[last];
    
    int score = std::max (score1, score2);
    mem[first][last] = score;
    
    return score;
}

std::tuple<int, int> scores (const std::vector<int> &A) {
    int n = A.size();
    sum = std::accumulate (A.begin(), A.end(), 0);
    sum_left = sum;
    for (int i = 0; i < n; ++i) {
        mem.emplace_back (std::vector<int> (n, -1));
    }
    for (int i = 0; i < n; ++i) mem[i][i] = A[i];

    int scoreA = score_rec (A, 0, n-1);
    int scoreB = sum - scoreA;
    
    return {scoreA, scoreB};
}

int main () {
    std::vector<int> A = {4, 5, 1, 3};
    auto[scoreA, scoreB] = scores (A);
    std::cout << scoreA << " " << scoreB << std::endl;
    return 0;
}