0

Good evening. Apologies if the question is poorly formated as it's my first time posting here.

I'm looking for aid with a particular exercise, as I've brainstormed for almost two hours now and can't find any suitable solution. The exercise is as follows: given a certain number of wagons, two thieves will be competing for the highest profit.

The first thief, let's say A, gets to start picking first. The thieves may pick either the first or the last wagon currently available on the list. The picked wagon is then removed from the list and its value is added to a counter for that respective thief. The objective of the exercise is to obtain the highest possible profit for thief A while also ensuring thief B is attempting to do the same.

If for example, we have the following input:

6
10
150
3
7
9
9

It means there are 6 wagons, with values 10, 150, 3, 7, 9 and 9 respectfully. If following an optimal strategy, the output should be 166, assuming both thieves follow the optimal strategy. However, so far, all I've managed to obtain is 169, which is theoretically the highest result thief A can obtain regardless of how thief B plays.

I'm not seeing how I can ensure both thieves follow the optimal strategy code-wise. It's supposedly an exercise where you must check for all possible combinations, but how can I look at the results and figure out in which both thieves followed an optimal strategy? Any ideas?

The code:

#include <stdio.h>
#include <stdlib.h>

#define DEBUG 0

int max = 0;
int diff = 9999;

int heist(int *wagons, int i, int j, int carry, int turn, int pos){
    #if DEBUG
    printf("DEBUG! i: %d || j: %d || carry: %d || turn: %d || post: %d || max: %d\n",i,j,carry,turn,pos,max);
    #endif
    /* Stopping condition */
    if (i==j){
        if (turn) carry += wagons[i];
        if (carry>=max){
            max = carry;
        }
        return 0;
    }
    if (!pos){
        /* First wagon */
        if (turn) carry += wagons[i];
        i++;
    } else {
        /* Last wagon */
        if (turn) carry += wagons[j];
        j--;
    }
    turn = !turn;
    heist(wagons,i,j,carry,turn,0);
    heist(wagons,i,j,carry,turn,1);
    return 0;
}

int main()
{
    /* Variables */
    int n;
    scanf("%d",&n);
    if (!n){
        printf("0\n");
        return 0;
    }
    int wagons[n];
    int i;
    /* Inputs */
    for (i=0;i<n;i++){
        scanf("%d",&wagons[i]);
    }
    heist(wagons,0,n-1,0,1,0);
    heist(wagons,0,n-1,0,1,1);
    printf("%d\n",max);
    return 0;
}
alk
  • 69,737
  • 10
  • 105
  • 255

2 Answers2

1

Your algorithm explores all possibilities and computes the maximum result for thief A. No surprise you get the best possible score for thief A if thief B uses the worst possible strategy.

You must find the best possible score for thief A for all possible strategies for thief B

For each move for thief A, compute the best strategy for thief B and select the move by A that minimizes that. Iterate.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I get what you mean, I'm just having a very hard time visualizing how to do that in terms of code. I've looked at Alpha-Beta Pruning as yossico suggested but I'm failing to see how I could apply it to the problem in question, given how I need to take the total sum into account. – MoonZapdos Feb 22 '15 at 14:17
  • Instead of updating a global variable with the score, update 2 sets of local variables with scores for A and B. Select the appropriate one according to the turn. A can choose its move, but must assume B's move can be optimal. Put more simply: each thief in turn chooses the best move and updates the caller's scores accordingly. – chqrlie Feb 22 '15 at 14:55
0

You need an evaluation function that returns the score of both players from a given starting position, assuming both play optimally.

#include <stdio.h>

#define N 6

const int WAGONS[N] = { 10, 150, 3, 7, 9, 9 };

// note: SCORE is used as output only
void heist (int score[2], const int *wagons, int i, int j, int player)
{
    if (i > j) {
        score[0] = 0;
        score[1] = 0;
    }
    else {
        int score_first[2];
        int score_last[2];

        // calculate outcome when taking the first element
        heist (score_first, wagons, i + 1, j, 1 - player);
        score_first[player] += wagons[i];


        // calculate outcome when taking the last element
        heist (score_last, wagons, i, j - 1, 1 - player);
        score_last[player] += wagons[j];


        // select optimal choice
        if (score_first[player] > score_last[player]) {
            score[0] = score_first[0];
            score[1] = score_first[1];
        }
        else {
            score[0] = score_last[0];
            score[1] = score_last[1];
        }
    }
}

int main ()
{
    int score[2];

    heist (score, WAGONS, 0, N - 1, 0);
    printf("%d, %d\n", score[0], score[1]);

    return 0;
}