需要动态编程解决方案

时间:2014-07-18 17:52:05

标签: java algorithm recursion dynamic-programming

problem如下:

给出一个字符矩阵。在游戏的最开始,我在矩阵中的位置(0,0)。根据当前位置(i,j)中的字符,我可以向上移动(如果当前字符是'U'),如果当前字符是'D'则向下移动,如果当前字符是'R'则向右移动,如果当前字符是'R'则向右移动当前字符为'L'。一旦我到达角色'*'的位置,我就不能再移动了(只有一个这样的位置)。我有一些时间K,我必须达到这个角色。我也有权改变角色,s.t。我可以更快地达到'*'字符,但是对于每次更改,我支付的费用为1.最后,我必须返回我执行的最小数量的更改。我必须在时间k到达'*'字符。如果不可能,我必须返回-1。

我的想法如下:

  1. 遍历整个矩阵,找到字符'*'的位置。

  2. 创建布尔方法isReachable(x, y, k),它告诉我位置(x, y)的字符是否可以从位置(0, 0)到达时间k。这是方法:

    public static boolean isReachable(int x, int y, int time){
        if(time < 0){
            return false;
        }
        if(x == 0 && y == 0){
            return true;
        }
        if(isInBounds(x-1, y)){
            if(maze[x-1][y] == 'D'){
                return isReachable(x-1, y, time-1);
            }
        }
        if(isInBounds(x, y-1)){
            if(maze[x][y-1] == 'R'){
                return isReachable(x, y-1, time-1);
            }
        }
        if(isInBounds(x+1, y)){
            if(maze[x+1][y] == 'U'){
                return isReachable(x+1, y, time-1);
            }
        }
        if(isInBounds(x, y+1)){
            if(maze[x][y+1] == 'L'){
                return isReachable(x, y+1, time-1);
            }
        }
        return false;
        }
    
        private static boolean isInBounds(int x, int y) {
        if(x >= 0 && x <= N-1 && y >= 0 && y <= M-1){
            return true;
        }
        return false;
    }
    
  3. 如果方法返回true - 我输出0(即不需要改变矩阵中的任何方格)。

    如果方法返回false - 我想执行另一种方法,它会告诉我最小的更改次数。但是我不知道如何写它。这是我的草案,它似乎不起作用:

    private static int find(int x, int y, int k) {
        int res = 0;
        if(k < 0){  //my idea is that if the time become < 0 it means that the point is unreachable, i.e. I have to output 0; Howevr this doesnt output 0, just gives 0 to the upper levels of a recursion tree;
            return -1;
        }
        if(x == 0 && y == 0){
            res = 0;
        }
        else{
            int down;
            if(isInBounds(x-1, y) ){
                if(maze[x-1][y] == 'D'){
                    down = find(x-1, y, k-1);
                }
                else{
                    down = 1 + find(x-1, y, k-1);
                }
            }
            else{
                down = Integer.MAX_VALUE;
            }
            int left;
            if(isInBounds(x, y+1) ){
                if(maze[x][y+1] == 'L'){
                    left = find(x, y+1, k-1);
                }
                else{
                    left = 1 + find(x, y+1, k-1);
                }
            }
            else{
                left = Integer.MAX_VALUE;
            }
            int right;
            if(isInBounds(x, y-1) ){
                if(maze[x][y-1] == 'R'){
                    right = find(x, y-1, k-1);
                }
                else{
                    right = 1 + find(x, y-1, k-1);
                }
            }
            else{
                right = Integer.MAX_VALUE;
            }
            int up;
            if(isInBounds(x+1, y) ){
                if(maze[x+1][y] == 'U'){
                    up = find(x+1, y, k-1);
                }
                else{
                    up = 1 + find(x+1, y, k-1);
                }
            }
            else{
                up = Integer.MAX_VALUE;
            }
            res = min(left, right, up, down);
        }
        return res;
    }
    

    正如我在评论中所写,我有两个非常基本的案例,我不知道如何执行:

    • 时间&lt; 0 - &gt;这意味着该点无法访问,即我必须输出-1(但我不知道该怎么做)
    • 如果我在点(0,0),我不需要做任何改变 - 返回0
    • 否则我会检查邻近的广场上的字母,然后将它们归还给他们。

    有人可以用一般的想法帮助我,因为我认为我的错了。我的问题描述据说我们必须使用动态编程和递归

1 个答案:

答案 0 :(得分:0)

我还没有解决问题,但我认为我的解决方案是正确的。 create dp [i] [j] [dir] [step],表示pos(i,j)的成本,方向是dir,需要&#39; step&#39;走到位置&#39; *&#39;。

假设&#39; *&#39;在I,J中,所以我们需要计算dp [I] [J] [0 | 1 | 2 | 3] [0]。 tot time是states * move,即(50 * 50 * 4 * 1000)*(4 * 4)。这足以解决问题。