将此递归解决方案转换为DP

时间:2014-06-30 04:23:17

标签: 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解决方案,因为它显然是指数级的。我正在努力解决这样一个事实:它有三个维度:你的选择数,对手的选择数和子问题大小,即似乎table[p][o][n]的最佳解决方案需要要维护,p是您选择的值的数量,o是您的对手选择的数字,n是子问题的大小。

我真的需要3个尺寸吗?我已经看到了类似的问题:http://www.geeksforgeeks.org/dynamic-programming-set-31-optimal-strategy-for-a-game/,但似乎无法适应它。

1 个答案:

答案 0 :(得分:4)

以下问题可以转换为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 stacksum[i] is sum of all elements on the stack from i onwards。可以使用 O(N)中的单独DP来评估sum[i]。可以使用 O(N)

中的表来解决上述DP

编辑: - 以下是JAVA中的DP解决方案: -

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。作为第二个玩家也能以最佳方式进行游戏,我们可以用递归方式表达解决方案。