📌  相关文章
📜  到达目的地的最低初始点

📅  最后修改于: 2021-04-23 22:22:12             🧑  作者: Mango

给定一个网格,每个单元格由正,负或无点组成,即零点。仅当我们有正点(> 0)时,我们才能跨单元格移动。每当我们经过一个单元格时,该单元格中的点都会添加到我们的总体点中。我们需要找到从(0,0)到达像元(m-1,n-1)的最小初始点。

限制条件:

  • 从一个单元(i,j),我们可以移至(i + 1,j)或(i,j + 1)。
  • 如果您在(i,j)的总分小于等于0,我们将无法从(i,j)移开。
  • 我们必须达到(n-1,m-1)的最小正点,即> 0。

    例子:

    Input: points[m][n] = { {-2, -3,   3}, 
                            {-5, -10,  1}, 
                            {10,  30, -5} 
                          };
    Output: 7
    Explanation: 
    7 is the minimum value to reach destination with 
    positive throughout the path. Below is the path.
    
    (0,0) -> (0,1) -> (0,2) -> (1, 2) -> (2, 2)
    
    We start from (0, 0) with 7, we reach(0, 1) 
    with 5, (0, 2) with 2, (1, 2) with 5, (2, 2)
    with and finally we have 1 point (we needed 
    greater than 0 points at the end). 

    我们强烈建议您单击此处并进行实践,然后再继续解决方案。

    乍一看,这个问题看起来与“最大/最小成本路径”相似,但获得的最大总积分将不能保证最低的初始积分。另外,在当前问题中必须强制这些点永远不要下降到零或以下。例如,假设存在从源到目标单元格的以下两条路径。

    我们可以通过自下而上的表格填充动态编程技术来解决此问题。

    • 首先,我们应维护一个与网格大小相同的2D数组dp,其中dp [i] [j]代表最小点,该最小点保证了进入单元(i,j)之前继续到达目的地的旅程。但很明显dp [0] [0]是我们的最终解决方案。因此,对于此问题,我们需要从右下角到左上角填充表格。
    • 现在,让我们确定离开像元(i,j)所需的最低点(记住,我们正在从下往上移动)。只有两条路径可供选择:(i + 1,j)和(i,j + 1)。当然,我们将选择玩家可以以较小的初始点完成其余旅程的单元。因此,我们有: min_Points_on_exit = min(dp [i + 1] [j],dp [i] [j + 1])

    现在我们知道了如何计算min_Points_on_exit,但是我们需要填充表dp [] []以获得dp [0] [0]中的解。

    如何计算dp [i] [j]?
    dp [i] [j]的值可以写成如下形式。

    dp [i] [j] = max(min_Points_on_exit – points [i] [j],1)

    让我们看看上面的表达式如何涵盖所有情况。

    • 如果points [i] [j] == 0,则在该单元格中什么也不会获得;玩家可以离开房间进入相同的点数,即dp [i] [j] = min_Points_on_exit。
    • 如果points [i] [j] <0,则玩家必须在进入(i,j)之前获得大于min_Points_on_exit的积分,以补偿该单元格中丢失的积分。最小补偿量为“ – points [i] [j]”,因此我们有dp [i] [j] = min_Points_on_exit – points [i] [j]。
    • 如果points [i] [j]> 0,则玩家可以输入的点数最少为min_Points_on_exit – points [i] [j]进入(i,j)。因为他可以在该单元格中获得“ points [i] [j]”分。但是,在这种情况下,min_Points_on_exit – points [i] [j]的值可能会降至0或以下。发生这种情况时,我们必须将值裁剪为1,以确保dp [i] [j]保持正值:
      dp [i] [j] = max(min_Points_on_exit – points [i] [j],1)。

    最后返回dp [0] [0],这就是我们的答案。

    下面是上述算法的实现。

    C++
    // C++ program to find minimum initial points to reach destination
    #include
    #define R 3
    #define C 3
      
    using namespace std;
      
    int minInitialPoints(int points[][C])
    {
        // dp[i][j] represents the minimum initial points player
        // should have so that when starts with cell(i, j) successfully
        // reaches the destination cell(m-1, n-1)
        int dp[R][C];
        int m = R, n = C;
      
        // Base case
        dp[m-1][n-1] = points[m-1][n-1] > 0? 1:
                       abs(points[m-1][n-1]) + 1;
      
        // Fill last row and last column as base to fill
        // entire table
        for (int i = m-2; i >= 0; i--)
             dp[i][n-1] = max(dp[i+1][n-1] - points[i][n-1], 1);
        for (int j = n-2; j >= 0; j--)
             dp[m-1][j] = max(dp[m-1][j+1] - points[m-1][j], 1);
      
        // fill the table in bottom-up fashion
        for (int i=m-2; i>=0; i--)
        {
            for (int j=n-2; j>=0; j--)
            {
                int min_points_on_exit = min(dp[i+1][j], dp[i][j+1]);
                dp[i][j] = max(min_points_on_exit - points[i][j], 1);
            }
         }
      
         return dp[0][0];
    }
      
    // Driver Program
    int main()
    {
      
        int points[R][C] = { {-2,-3,3},
                          {-5,-10,1},
                          {10,30,-5}
                        };
        cout << "Minimum Initial Points Required: "
             << minInitialPoints(points);
        return 0;
    }


    Java
    class min_steps
    {
        static int minInitialPoints(int points[][],int R,int C)
        {
            // dp[i][j] represents the minimum initial points player
            // should have so that when starts with cell(i, j) successfully
            // reaches the destination cell(m-1, n-1)
            int dp[][] = new int[R][C];
            int m = R, n = C;
           
            // Base case
            dp[m-1][n-1] = points[m-1][n-1] > 0? 1:
                           Math.abs(points[m-1][n-1]) + 1;
           
            // Fill last row and last column as base to fill
            // entire table
            for (int i = m-2; i >= 0; i--)
                 dp[i][n-1] = Math.max(dp[i+1][n-1] - points[i][n-1], 1);
            for (int j = n-2; j >= 0; j--)
                 dp[m-1][j] = Math.max(dp[m-1][j+1] - points[m-1][j], 1);
           
            // fill the table in bottom-up fashion
            for (int i=m-2; i>=0; i--)
            {
                for (int j=n-2; j>=0; j--)
                {
                    int min_points_on_exit = Math.min(dp[i+1][j], dp[i][j+1]);
                    dp[i][j] = Math.max(min_points_on_exit - points[i][j], 1);
                }
             }
           
             return dp[0][0];
        }
      
        /* Driver program to test above function */ 
        public static void main (String args[])
        {
              int points[][] = { {-2,-3,3},
                          {-5,-10,1},
                          {10,30,-5}
                        };
              int R = 3,C = 3;
              System.out.println("Minimum Initial Points Required: "+
                                                minInitialPoints(points,R,C) );
        }
    }/* This code is contributed by Rajat Mishra */


    Python3
    # Python3 program to find minimum initial
    # points to reach destination
    import math as mt
    R = 3
    C = 3
      
    def minInitialPoints(points):
        '''
        dp[i][j] represents the minimum initial
        points player should have so that when 
        starts with cell(i, j) successfully
        reaches the destination cell(m-1, n-1)
        '''
        dp = [[0 for x in range(C + 1)] 
                 for y in range(R + 1)]
        m, n = R, C
          
        if points[m - 1][n - 1] > 0:
            dp[m - 1][n - 1] = 1
        else:
            dp[m - 1][n - 1] = abs(points[m - 1][n - 1]) + 1
        '''
        Fill last row and last column as base
        to fill entire table
        '''
        for i in range (m - 2, -1, -1):
            dp[i][n - 1] = max(dp[i + 1][n - 1] -
                               points[i][n - 1], 1)
        for i in range (2, -1, -1):
            dp[m - 1][i] = max(dp[m - 1][i + 1] -
                               points[m - 1][i], 1)
        '''
        fill the table in bottom-up fashion
        '''
        for i in range(m - 2, -1, -1):
            for j in range(n - 2, -1, -1):
                min_points_on_exit = min(dp[i + 1][j],
                                         dp[i][j + 1])
                dp[i][j] = max(min_points_on_exit -
                                   points[i][j], 1)
                  
        return dp[0][0] 
          
    # Driver code
    points = [[-2, -3, 3],
              [-5, -10, 1],
              [10, 30, -5]]
      
    print("Minimum Initial Points Required:", 
                    minInitialPoints(points))
      
      
    # This code is contributed by 
    # Mohit kumar 29 (IIIT gwalior)


    C#
    // C# program Minimum Initial Points
    // to Reach Destination
    using System;
    class GFG {
          
        static int minInitialPoints(int [,]points, 
                                     int R, int C)
        {
              
            // dp[i][j] represents the 
            // minimum initial points 
            // player should have so 
            // that when starts with 
            // cell(i, j) successfully
            // reaches the destination
            // cell(m-1, n-1)
            int [,]dp = new int[R,C];
            int m = R, n = C;
          
            // Base case
            dp[m - 1,n - 1] = points[m - 1, n - 1] > 0 ? 1:
                         Math.Abs(points[m - 1,n - 1]) + 1;
          
            // Fill last row and last 
            // column as base to fill
            // entire table
            for (int i = m-2; i >= 0; i--)
                dp[i, n - 1] = Math.Max(dp[i + 1, n - 1] - 
                                    points[i, n - 1], 1);
            for (int j = n - 2; j >= 0; j--)
                dp[m - 1, j] = Math.Max(dp[m - 1, j + 1] - 
                                    points[m - 1, j], 1);
          
            // fill the table in 
            // bottom-up fashion
            for(int i = m - 2; i >= 0; i--)
            {
                for (int j = n - 2; j >= 0; j--)
                {
                    int min_points_on_exit = Math.Min(dp[i + 1, j], 
                                                      dp[i, j + 1]);
                    dp[i, j] = Math.Max(min_points_on_exit - 
                                          points[i, j], 1);
                }
            }
          
            return dp[0, 0];
        }
      
        // Driver Code
        public static void Main ()
        {
            int [,]points = {{-2,-3,3},
                             {-5,-10,1},
                               {10,30,-5}};
            int R = 3,C = 3;
            Console.Write("Minimum Initial Points Required: "+
                               minInitialPoints(points, R, C));
        }
    }
      
    // This code is contributed by nitin mittal.


    PHP
     0 ? 1 : 
                          abs($points[$m - 1][$n - 1]) + 1;
      
        // Fill last row and last column as 
        // base to fill entire table
        for ($i = $m - 2; $i >= 0; $i--)
            $dp[$i][$n - 1] = max($dp[$i + 1][$n - 1] - 
                                  $points[$i][$n - 1], 1);
        for ($j = $n - 2; $j >= 0; $j--)
            $dp[$m - 1][$j] = max($dp[$m - 1][$j + 1] - 
                                  $points[$m - 1][$j], 1);
      
        // fill the table in bottom-up fashion
        for ($i = $m - 2; $i >= 0; $i--)
        {
            for ($j = $n - 2; $j >= 0; $j--)
            {
                $min_points_on_exit = min($dp[$i + 1][$j], 
                                          $dp[$i][$j + 1]);
                $dp[$i][$j] = max($min_points_on_exit - 
                                  $points[$i][$j], 1);
            }
        }
      
        return $dp[0][0];
    }
      
    // Driver Code
    $points = array(array(-2, -3, 3),
                    array(-5, -10, 1),
                    array(10, 30, -5));
                  
    echo "Minimum Initial Points Required: ",
                   minInitialPoints($points);
      
    // This code is contributed by akt_mit
    ?>


    输出:

    Minimum Initial Points Required: 7