使用两次遍历收集网格中的最大点

dynamic programmingalgorithmsdata structure

每个单元格中都有一个点的矩阵,如何使用两次遍历从该网格中获得最大点。

有一些条件需要满足−

  • 第一次遍历从网格的左上角单元格开始,应该到达左下角。     第二次遍历从右上角开始到右下角
  • 从一个单元格我们只能移动到当前单元格的底部、左下角和右下角。
  • 如果一次遍历已经从某个单元格获得一些点,则在下一次遍历中不会从该单元格获得任何点。

输入和输出

输入:
A grid with points.
3 6  8  2
5 2  4  3
1 1 20 10
1 1 20 10
1 1 20 10

输出:
Maximum points collected by two traversals is 73.
From the first traversal, it gains: 3 + 2 + 20 + 1 + 1 = 27
From the second traversal, it gains: 2 + 4 + 10 + 20 + 10 = 46

算法

findMaxVal(mTable, x, y1, y2)

输入 − 一个三维数组作为记忆表,x值和y1,y2。

输出 − 最大值。

Begin
   if x, y1 and y2 is not valid, then
      return - ∞
   if both traversal is complete, then
      if y1 = y2, then
         return grid[x, y1]
      else
         return grid[x, y1] + grid[x, y2]
   if both traversal are at last row, then
      return - ∞
   if subProblem is solved, then
      return mTable[x, y1, y2]
   set res := - ∞

   if y1 = y2, then
      temp := grid[x, y1]
   else
      temp := grid[x, y1] + grid[x, y2]

   res := max of res and (temp + findMaxVal(mTable, x+1, y1, y2-1))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1, y2+1))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1, y2))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1-1, y2))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1-1, y2-1))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1-1, y2+1))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1+1, y2))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1+1, y2-1))
   res := max of res and (temp + findMaxVal(mTable, x+1, y1+1, y2+1))

   return true if mTable[x, y1, y2] = res
End

示例

#include<iostream>
#define ROW 5
#define COL 4
using namespace std;

int grid[ROW][COL] = {
   {3, 6, 8, 2},
   {5, 2, 4, 3},
   {1, 1, 20, 10},
   {1, 1, 20, 10},
   {1, 1, 20, 10},
};

bool isValidInput(int x, int y1, int y2) {
   return (x >= 0 && x < ROW && y1 >=0 && y1 < COL && y2 >=0 && y2 < COL);
}

int max(int a, int b) {
   return (a>b)?a:b;
}

int findMaxVal(int mTable[ROW][COL][COL], int x, int y1, int y2) {
   if (!isValidInput(x, y1, y2))    //当在无效单元格中时,返回负无穷
      return INT_MIN;

   if (x == ROW-1 && y1 == 0 && y2 == COL-1)    //当两个遍​​历都完成时  
      return (y1 == y2)? grid[x][y1]: grid[x][y1] + grid[x][y2];

   if (x == ROW-1)       //两次遍历都在最后一行但尚未完成

      return INT_MIN;

   if (mTable[x][y1][y2] != -1)    //当子问题解决时
      return mTab​​le[x][y1][y2];

   int answer = INT_MIN;       //最初答案是负无穷

   int temp = (y1 == y2)? grid[x][y1]: grid[x][y1] + grid[x][y2];    //存储当前房间的增益

   //找到所有可能值的答案并取其中的最大值

   answer = max(answer, temp + findMaxVal(mTable, x+1, y1, y2-1));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1, y2+1));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1, y2));

   answer = max(answer, temp + findMaxVal(mTable, x+1, y1-1, y2));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1-1, y2-1));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1-1, y2+1));

   answer = max(answer, temp + findMaxVal(mTable, x+1, y1+1, y2));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1+1, y2-1));
   answer = max(answer, temp + findMaxVal(mTable, x+1, y1+1, y2+1));

   return (mTable[x][y1][y2] = answer); //将答案存储在 mTab​​le 中并返回。
}

int findMaxCollection() {
   // 创建一个记忆表并将所有值设置为 -1
   int mTab​​le[ROW][COL][COL];

   for(int i = 0; i<ROW; i++)
      for(int j = 0; j<COL; j++)
         for(int k = 0; k<COL; k++)
            mTab​​le[i][j][k] = -1;

   return findMaxVal(mTable, 0, 0, COL-1);
}

int main() {
   cout << "最大集合为" << findMaxCollection();
   return 0;
}

输出

最大集合为 73

相关文章