给定大小为NXM的矩阵,其中包括“#”,“。”和 ‘*’。 “#”表示路径受阻,“。”表示可步行的路径,“ *”表示必须收集的点。现在考虑您在矩阵的左上方。您必须到达矩阵的右下角,然后回到左上角。当您从左上方移动到右下方时,您可以向右或向下行走。而且,当您从右下到左上移动时,您可以向左或向上行走。任务是找到您在整个旅程中可以获得的最高积分。一旦获得积分,将转换为“。”。即步行路径。
例子:
Input : N = 3, M = 4
****
.##.
.##.
****
Output : 8
Input : N = 9, M = 7
*........
.....**#.
..**...#*
..####*#.
.*.#*.*#.
...#**...
*........
Output : 7
如果考虑两条路径-一个从(0,0)到(N – 1,M – 1),另一个从(N – 1,M – 1)到(0,0),并在每个路径中收集最大*。您可能会得到错误的答案。如果分别添加两条路径的答案,则在回溯时将再次计算相交点。本质上,以相同的路径结束。即使您保留一个访问数组,并在第一个路径上标记每个*,您仍然不会得到正确的答案。
考虑以下示例:
如果我们考虑作为两条独立的路径,那么
总共*收集的是7。
而遵循以下路径可以收集的最大点数是8。
每个路径上有4 *。因此,总数= 8。
因此,我们看到最优解不是两个路径的最优解之和。一个人的最佳答案不能确保最佳答案。
因此,我们将必须同时计算两条路径。之所以需要这样做,是因为路径2的答案取决于路径1选择的路径。可以通过考虑从(0,0)到(N-1,M-1)的两条路径并在每个位置做出四个决策来完成同时计算。 (每个两个)。
因此,我们将同时从(0,0)到(N-1,M-1)两条路径,而不是从左上角到右下角的两条路径,而从(0,0)到(N-1,M-1)两条路径,一步,我们对这两个路径都迈出了一步。因此,我们的状态将由(x1,y1,x2,y2)组成,其中(x1,y1)是第一条路径的位置,而(x2,y2)是第二条游客在网格中的位置。
注意事项:
1.在每一步中,任一步都可以向右或向下移动,因此我们有4个移动选择(每个路径2个选择)。
2.如果两个路径都在同一个像元上(x1 == x2和y1 == y2),则如果该像元具有*,则只能加1。
3.我们可以通过将状态维数从4减小到3来降低复杂度。如果我们知道第一条路径(x1,y1)的位置是第二条路径x2的x坐标,那么由于x1 + y1 = x2 + y2两条路径在相同的时间内覆盖相同的距离。因此y2 = x1 + y1 – x2,我们的状态仅取决于(x1,y1,x2)。
以下是此方法的实现:
C++
// CPP program to find maximum points that can
// be collected in a journey from top to bottom
// and then back from bottom to top,
#include
#define MAX 5
#define N 5
#define M 5
#define inf 100000
using namespace std;
// Calculating the points at a (row1, col1) &&
// (row2, col2) from path1 && path2
int cost(char grid[][M], int row1, int col1,
int row2, int col2)
{
// If both path is at same cell
if (row1 == row2 && col1 == col2) {
// If the cell contain *, return 1
if (grid[row1][col1] == '*')
return 1;
// else return 0.
return 0;
}
int ans = 0;
// If path 1 contain *, add to answer.
if (grid[row1][col1] == '*')
ans++;
// If path contain *, add to answer.
if (grid[row2][col2] == '*')
ans++;
return ans;
}
// Calculate the maximum points that can be
// collected.
int solve(int n, int m, char grid[][M],
int dp[MAX][MAX][MAX], int row1,
int col1, int row2)
{
int col2 = (row1 + col1) - (row2);
// If both path reach the bottom right cell
if (row1 == n - 1 && col1 == m - 1 &&
row2 == n - 1 && col2 == m - 1)
return 0;
// If moving out of grid
if (row1 >= n || col1 >= m ||
row2 >= n || col2 >= m)
return -1 * inf;
// If already calculated, return the value
if (dp[row1][col1][row2] != -1)
return dp[row1][col1][row2];
// Variable for 4 options.
int ch1 = -1 * inf, ch2 = -1 * inf;
int ch3 = -1 * inf, ch4 = -1 * inf;
// If path 1 is moving right and path 2
// is moving down.
if (grid[row1][col1 + 1] != '#' &&
grid[row2 + 1][col2] != '#')
ch1 = cost(grid, row1, col1 + 1, row2 + 1, col2) +
solve(n, m, grid, dp, row1, col1 + 1, row2 + 1);
// If path 1 is moving right and path 2 is moving
// right.
if (grid[row1][col1 + 1] != '#' &&
grid[row2][col2 + 1] != '#')
ch2 = cost(grid, row1, col1 + 1, row2, col2 + 1) +
solve(n, m, grid, dp, row1, col1 + 1, row2);
// If path 1 is moving down and path 2 is moving right.
if (grid[row1 + 1][col1] != '#' &&
grid[row2][col2 + 1] != '#')
ch3 = cost(grid, row1 + 1, col1, row2, col2 + 1) +
solve(n, m, grid, dp, row1 + 1, col1, row2);
// If path 1 is moving down and path 2 is moving down.
if (grid[row1 + 1][col1] != '#' &&
grid[row2 + 1][col2] != '#')
ch4 = cost(grid, row1 + 1, col1, row2 + 1, col2) +
solve(n, m, grid, dp, row1 + 1, col1, row2 + 1);
// Returning the maximum of 4 options.
return dp[row1][col1][row2] = max({ch1, ch2, ch3, ch4});
}
// Wrapper Function
int wrapper(int n, int m, char grid[N][M])
{
int ans = 0;
int dp[MAX][MAX][MAX];
memset(dp, -1, sizeof dp);
// If last bottom right cell is blcoked
if (grid[n - 1][m - 1] == '#' || grid[0][0] == '#')
ans = -1 * inf;
// If top left cell contain *
if (grid[0][0] == '*')
ans++;
grid[0][0] = '.';
// If bottom right cell contain *
if (grid[n - 1][m - 1] == '*')
ans++;
grid[n - 1][m - 1] = '.';
ans += solve(n, m, grid, dp, 0, 0, 0);
return max(ans, 0);
}
// Driven Program
int main()
{
int n = 5, m = 5;
char grid[N][M] = {
{ '.', '*', '.', '*', '.' },
{ '*', '#', '#', '#', '.' },
{ '*', '.', '*', '.', '*' },
{ '.', '#', '#', '#', '*' },
{ '.', '*', '.', '*', '.' }
};
cout << wrapper(n, m, grid) << endl;
return 0;
}
Python3
# Python3 program to find maximum points
# that can be collected in a journey from
# top to bottom and then back from bottom to top,
MAX = 5
N = 5
M = 5
inf = 100000
# Calculating the points at a (row1, col1) and
# (row2, col2) from path1 and path2
def cost(grid, row1, col1, row2, col2):
# If both path is at same cell
if (row1 == row2 and col1 == col2):
# If the cell contain *, return 1
if (grid[row1][col1] == '*'):
return 1
# else return 0.
return 0
ans = 0
# If path 1 contain *, add to answer.
if (grid[row1][col1] == '*'):
ans += 1
# If path contain *, add to answer.
if (grid[row2][col2] == '*'):
ans += 1
return ans
# Calculate the maximum points that can be
# collected.
def solve(n, m, grid, dp, row1, col1, row2):
col2 = (row1 + col1) - (row2)
# If both path reach the bottom right cell
if (row1 == n - 1 and col1 == m - 1 and
row2 == n - 1 and col2 == m - 1):
return 0
# If moving out of grid
if (row1 >= n or col1 >= m or
row2 >= n or col2 >= m):
return -1 * inf
# If already calculated, return the value
if (dp[row1][col1][row2] != -1):
return dp[row1][col1][row2]
# Variable for 4 options.
ch1 = -1 * inf
ch2 = -1 * inf
ch3 = -1 * inf
ch4 = -1 * inf
# If path 1 is moving right and path 2
# is moving down.
if (col1 + 1 < m and row2 + 1 < n and
grid[row1][col1 + 1] != '#' and
grid[row2 + 1][col2] != '#'):
ch1 = cost(grid, row1, col1 + 1, row2 + 1, col2) + \
solve(n, m, grid, dp, row1, col1 + 1, row2 + 1)
# If path 1 is moving right and path 2
# is moving right.
if (col1 + 1 < m and col2 + 1 < m and
grid[row1][col1 + 1] != '#' and
grid[row2][col2 + 1] != '#'):
ch2 = cost(grid, row1, col1 + 1, row2, col2 + 1) + \
solve(n, m, grid, dp, row1, col1 + 1, row2)
# If path 1 is moving down and path 2
# is moving right.
if (row1 + 1 < n and col2 + 1 < m and
grid[row1 + 1][col1] != '#' and
grid[row2][col2 + 1] != '#'):
ch3 = cost(grid, row1 + 1, col1, row2, col2 + 1) + \
solve(n, m, grid, dp, row1 + 1, col1, row2)
# If path 1 is moving down and path 2 is moving down.
if (row1 + 1 < n and row2 + 1 < n and
grid[row1 + 1][col1] != '#' and
grid[row2 + 1][col2] != '#'):
ch4 = cost(grid, row1 + 1, col1, row2 + 1, col2) + \
solve(n, m, grid, dp, row1 + 1, col1, row2 + 1)
# Returning the maximum of 4 options.
dp[row1][col1][row2] = max(ch1, ch2, ch3, ch4)
return dp[row1][col1][row2]
# Wrapper Function
def wrapper(n, m, grid):
ans = 0
dp = [[[-1] * MAX for i in range(MAX)]
for j in range(MAX)]
# If last bottom right cell is blcoked
if (grid[n - 1][m - 1] == '#' or
grid[0][0] == '#'):
ans = -1 * inf
# If top left cell contain *
if (grid[0][0] == '*'):
ans += 1
grid[0][0] = '.'
# If bottom right cell contain *
if (grid[n - 1][m - 1] == '*'):
ans += 1
grid[n - 1][m - 1] = '.'
ans += solve(n, m, grid, dp, 0, 0, 0)
return max(ans, 0)
# Driver Code
if __name__ == '__main__':
n = 5
m = 5
grid = [[ '.', '*', '.', '*', '.' ],
[ '*', '#', '#', '#', '.' ],
[ '*', '.', '*', '.', '*' ],
[ '.', '#', '#', '#', '*' ],
[ '.', '*', '.', '*', '.' ]]
print(wrapper(n, m, grid))
# This code is contributed by ashutosh450
输出:
8
时间复杂度: O(N ^ 3)