Преобразование этого рекурсивного решения в DP

#algorithm #optimization #recursion #dynamic-programming

#алгоритм #оптимизация #рекурсия #динамическое программирование

Вопрос:

Учитывая стопку целых чисел, игроки по очереди удаляют 1, 2 или 3 числа из верхней части стека. Предполагая, что противник играет оптимально, и вы выбираете первым, я придумал следующую рекурсию:

 int score(int n) {
    if (n <= 0) return 0;

    if (n <= 3) {
        return sum(v[0..n-1]);
    }

    // maximize over picking 1, 2, or 3   value after opponent picks optimally
    return max(v[n-1]   min(score(n-2), score(n-3), score(n-4)),
               v[n-1]   v[n-2]   min(score(n-3), score(n-4), score(n-5)),
               v[n-1]   v[n-2]   v[n-3]   min(score(n-4), score(n-5), score(n-6)));
}
  

По сути, на каждом уровне сравниваются результаты выбора 1, 2 или 3, а затем ваш оппонент выбирает либо 1, 2, либо 3.

Мне было интересно, как я мог бы преобразовать это в решение DP, поскольку оно явно экспоненциально. Я боролся с тем фактом, что, похоже, у него есть 3 измерения: число вашего выбора, число выбора оппонента и размер подзадачи, т. Е. Кажется, Что лучшее решение для table[p][o][n] необходимо поддерживать, где p количество выбранных вами значений, o это число вашего оппонентавыбирает и n определяет размер подзадачи.

Мне действительно нужны 3 измерения? Я видел эту аналогичную проблему: http://www.geeksforgeeks.org/dynamic-programming-set-31-optimal-strategy-for-a-game / , но, похоже, не смог его адаптировать.

Комментарии:

1. можете ли вы привести простой пример, чтобы прояснить суть игры?

2. @VikramBhat (вершина стека)—>12 1 7 10 2 9 3. Вы можете либо добавить 12, 12 1, либо 12 1 7 на ваш счет. Эти числа удаляются из стека, а затем ваш оппонент выбирает 1, 2 или три числа из оставшегося стека. Вы продолжаете по очереди, пока не останется ни одного числа.

3. тогда выигрывает тот, у кого максимальное количество, верно?

4. @VikramBhat правильно. Как и в случае с максимальной суммой накопленных числовых значений — максимальная оценка.

5. @KarolyHorvath запоминание технически не равно DP. DP — снизу вверх, тогда как memoization — сверху вниз и также использует stack. Вы можете сэкономить много места в DP. Например, эту проблему можно решить в O (1) дополнительном пространстве, используя DP, просто сохранив последние три решения.

Ответ №1:

Вот способ, которым проблема может быть преобразована в DP :-

 score[i] = maximum{ sum[i] - score[i 1] , sum[i] - score[i 2] , sum[i] - score[i 3]  } 
  

Вот score[i] means max score generated from game [i to n] где v[i] is top of stack . sum[i] is sum of all elements on the stack from i onwards . sum[i] может быть оценен с использованием отдельного DP в O (N) . Вышеупомянутый DP может быть решен с помощью таблицы в O (N)

Редактировать : — Ниже приведено решение DP на JAVA :-

 public class game {

    static boolean play_game(int[] stack) {
        if(stack.length<=3)
            return true;
        int[] score = new int[stack.length];
        int n = stack.length;
        score[n-1] = stack[n-1];
        score[n-2] = score[n-1] stack[n-2];
        score[n-3] = score[n-2] stack[n-3];
        int sum = score[n-3]; 
        for(int i=n-4;i>=0;i--) {
            sum = stack[i] sum;
            int min = Math.min(Math.min(score[i 1],score[i 2]),score[i 3]);
            score[i] = sum-min;
        }
        if(sum-score[0]<score[0]) 
            return true;

        return false;
    }

    public static void main(String args[]) {
        int[] stack = {12,1,7,99,3};
        System.out.printf("I win => " play_game(stack));
    }
  

Редактировать:-

Для получения решения DP вам необходимо визуализировать решение проблемы в терминах меньших экземпляров самого себя. Например, в этом случае, поскольку оба игрока играют оптимально, после выбора, сделанного первым, второй игрок также получает оптимальный счет для оставшегося стека, который является подзадачей первого. Единственная проблема здесь заключается в том, как представить его в повторении. Чтобы решить DP, вы должны сначала определить рекуррентное отношение в терминах подзадачи, которая предшествует текущей задаче при любом способе вычисления. Теперь мы знаем, что независимо от того, что выигрывает второй игрок, первый игрок проигрывает, поэтому первый игрок выигрывает total sum - score у второго игрока. Поскольку второй игрок также играет оптимально, мы можем выразить решение в терминах рекурсии.

Комментарии:

1. Я вижу, что это работает и что он делает и т.д., Однако мне было интересно, как вы пришли к этому; какой-либо конкретный метод? Есть ли какое-либо интуитивное объяснение для его объединения?

2. @alh по сути, вам нужно найти рекуррентное соотношение в терминах меньших проблем, которые могут быть оценены независимо. Проверьте мое редактирование.