我最近在解决这个问题:
在一个巨大的果园里,你发现自己置身于m行n列的苹果树中,每棵树上都有一定数量的成熟苹果,用矩阵网格表示。这个矩阵的维数为m × n,表示你的苹果田,其中grid[i][j]
表示你可以从树的位置(i,j)收集到的苹果数量。
为了帮助你采摘苹果,你有两个专门的果农:
- 果农1,驻守左上角(0,0)
- 果农2,驻守右上角(0,n - 1)
- 你的目标是设计一个计划,最大限度地提高总数量的苹果收集的农民
按照以下规则打印这两个勤劳的果农可以收集的苹果的最大数量:
- 从任何单元格(i,j),农民可以移动到下一行中的以下相邻单元格之一:左下(i + 1,j - 1)、向下(i + 1,j)或右下(i + 1,j + 1)
- 每当一个农民经过一个细胞,他们立即收集所有的苹果从这棵树,树是空的
- 如果两个农民碰巧降落在同一个小区,他们必须分享苹果,但只有一个农民可以收集它们。
- 农民们在任何时候都不允许冒险离开果园
- 两个农民都必须到达果园的最下面一排才能完成摘苹果的使命
我很难理解两个农民是如何互动的。这道题我怎么解?
我想出了使用动态规划来解决每个农民的每个网格最大收获。但我不知道如何解决这个问题。
我的代码:
#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 100
#define MAX_COLS 100
int main() {
int m = 3;
int n = 3;
//example
int grid[MAX_ROWS][MAX_COLS] = {
{3, 1, 1},
{5, 6, 2},
{9, 6, 7}
};
int dp[MAX_ROWS][MAX_COLS] = { 0 };
for (int j = 0; j < n; j++) {
dp[m - 1][j] = grid[m - 1][j];
}
for (int i = m - 2; i >= 0; i--) {
for (int j = 0; j < n; j++) {
dp[i][j] = grid[i][j] + dp[i + 1][j];
if (j > 0) {
dp[i][j] = max(dp[i][j], grid[i][j] + dp[i + 1][j - 1]);
}
if (j < n - 1) {
dp[i][j] = max(dp[i][j], grid[i][j] + dp[i + 1][j + 1]);
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf("%d ",dp[i][j]);
}
printf("\n");
}
return 0;
}
结果:
18 16 16
14 15 9
9 6 7
2条答案
按热度按时间hjqgdpho1#
目前还不清楚农民必须采取相同的回合数,所以让我们假设在每次迭代中,我们有多达6个选项:农民1向下_左、下、右下移动,农民2也是如此。
当农民处于边缘或底部时,计数可以小于6。
请注意,没有循环。每个农民最终都会使
MAX_ROWS-1
向下移动。解决方案涉及递归。
考虑 * 状态 *:
int grid[MAX_ROWS][MAX_COLS]
int farmer_row[2]; int farmer_col[2]
int move_count
(初始值为0)int move[(MAX_ROWS - 1) * 2]
来记录6步中的哪一步。(无需初始化)1.初始化状态
1.调用递归
function(state)
。尝试每一个6移动保持跟踪,如果至少有一个是法律的。
B.对于每一步:走一步并记录下最好的一步,(最大的苹果和-递归返回值)。返回值-1表示递归未能达到法律的结束状态。
C.如果在最后一步和苹果总和比最好的苹果总和好,复制总和和移动列表到最好的。
D.每次移动:撤消移动的效果。
E.如果没有找到法律的移动返回-1,否则返回最佳和。
1.报告最好的总和和移动列表。
更高级的方法将预先计算每行最高的2棵树的总和,并在检查6种可能的移动和当前总和时使用。如果每个农民的当前和+剩余行中最好的2行小于先前移动的和,则不需要递归该移动。
i1icjdpr2#
解决这个问题的一种方法可能是同时考虑这两种立场。
Python代码: