给定一个网格,每个单元格由正,负或无点组成,即零点。仅当我们有正点(> 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