Improving recursion method in C #

This is my code:

    static int cardGameValue(List<int> D, int myScore, int opponentScore)
    {
        if (D.Count == 0) return myScore;
        else if (D.Count == 1)
        {
            opponentScore += D[0];
            return myScore;
        }
        else
        {
            if (D[0] <= D[D.Count - 1])
            {
                opponentScore += D[D.Count - 1];
                D.RemoveAt(D.Count - 1);
            }
            else
            {
                opponentScore += D[0];
                D.RemoveAt(0);
            }

            int left = cardGameValue(new List<int>(D.GetRange(1, D.Count - 1)), myScore + D[0], opponentScore);

            int right = cardGameValue(new List<int>(D.GetRange(0, D.Count - 1)), myScore + D[D.Count - 1], opponentScore);

            if (left >= right)
            {
                return left;
            }
            else
            {
                return right;
            }
        }
    }
}

My code takes a set of cards and presents your maximum possible score when playing against a deterministic opponent. After each of your opponents, you have 2 options until all cards are selected. Is there a way to somehow save my iteration results so that I can improve my algorithm? So recursion doesn't do unnecessary iterations? Because after 40 or 50 cards it becomes very slow.

+5
source share
3 answers

D. , , ( : int) .

, : myScore opponentScore , O (n) . , , opponentScore.

myScore. cardGameValue , .

, , 2D-, first last. , , .

, . , . , , .

:

static int cardGameValue(int[] D, int first, int last) {
    scores = new int[last + 1, last + 1];
    return cardGameValue(D, first, last, scores);
}

static int cardGameValue(int[] D, int first, int last, int[,] scores) {
    // If we have at most 1 card, our score is 0:
    if (first >= last)
        return 0;

    // Otherwise, get the score from the cache array. 
    // If it is positive, return the value.
    int score = scores[first, last];
    if (score > 0)
        return score;

    // Keep the original first and last 
    // for filling in the computed value later.
    int firstOriginal = first;
    int lastOriginal = last;

    // Let the opponent pick a card:
    if (D[first] <= D[last])
        last--;
    else
        first++;

    // Choose our best card:
    int left = D[first] + cardGameValue(D, first + 1, last, scores);
    int right = D[last] + cardGameValue(D, first, last - 1, scores);
    score = Math.Max(left, right);

    // and enter the score into the cache array:
    scores[firstOriginal, lastOriginal] = score;

    // Finally, return the computed score.
    return score;
}

300 1 .

+3

, , , !

2- int. [i][j] D[i] D[j]. 0, 1 . O (n ^ 2) .

+2

List, , GetRange List, , , 2 4 . , .

        int left = cardGameValue(new List<int>(D.GetRange(1, D.Count - 1)), myScore + D[0], opponentScore);

        int right = cardGameValue(new List<int>(D.GetRange(0, D.Count - 1)), myScore + D[D.Count - 1], opponentScore);

, , startIndex length, cardGameValue List.

static int cardGameValue(List<int> D, int startIndex, int length, int myScore, int opponentScore)

, :

        int left = cardGameValue(D, startIndex + 1, length - 1, myScore + D[startIndex], opponentScore);

        int right = cardGameValue(D, startIndex, length - 1, myScore + D[startIndex + length - 1], opponentScore);

i.e. Code that refers to an index 0, such as D[0]and D.RemoveAt(0), will need to be modified to use startIndex, such as D[startIndex]and D.RemoveAt(startIndex). The code that refers to D.Countshould be replaced by startIndex + length. Correction: code that refers to D.Count - 1should be replaced either length - 1by or startIndex + length - 1(depending on context), but code that just refers to D.Countwill simply be replaced by length.

+1
source

All Articles