1219. Gold miners
You want to develop a gold mine. Geological surveyors have identified the distribution of resources in the gold mine and marked it with a grid of size m * n. The integer in each cell represents the amount of gold in this cell; If the cell is empty, it is 0.
In order to maximize profits, miners need to mine gold according to the following rules:
Every time a miner enters a cell, he collects all the gold in that cell.
Miners can walk up, down, left and right from their current position at a time.
Each cell can only be mined (entered) once.
Do not mine (enter) cells with a gold number of 0.
Miners can start from any cell with gold in the grid or stop.
Example 1:
Input: grid = [[0,6,0],[5,8,7],[0,9,0]]
Output: 24
Explanation:
[[0,6,0],
[5,8,7],
[0,9,0]]
One route to collect the most gold is: 9 - > 8 - > 7.
Example 2:
Input: grid = [[1,0,7],[2,0,6],[3,4,5],[0,3,0],[9,0,20]]
Output: 28
Explanation:
[[1,0,7],
[2,0,6],
[3,4,5],
[0,3,0],
[9,0,20]]
One route to collect the most gold is: 1 - > 2 - > 3 - > 4 - > 5 - > 6 - > 7.
Tips:
1 <= grid.length, grid[i].length <= 15
0 <= grid[i][j] <= 100
There is gold in up to 25 cells.
At the beginning, I just wanted recursion and backtracking
But I thought it was troublesome, so I used value passing
class Solution { private: vector<vector<int>> _grid; int getGold(int i, int j, vector<vector<int>> flagCache, int totalGold) { if(i<0||j<0) return totalGold; if(i>=_grid.size()) return totalGold; if(j>=_grid[i].size()) return totalGold; if(_grid[i][j] == 0||flagCache[i][j] == 1) return totalGold; flagCache[i][j] = 1; vector<int> goldNumCache; goldNumCache.push_back(getGold(i-1,j,flagCache,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i+1,j,flagCache,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j-1,flagCache,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j+1,flagCache,totalGold + _grid[i][j])); sort(goldNumCache.begin(),goldNumCache.end()); return goldNumCache.back(); } public: int getMaximumGold(vector<vector<int>>& grid) { _grid = grid; vector<vector<int>> _flag = vector<vector<int>>(grid.size()); for(int i=0;i<grid.size();i++) _flag[i] = vector<int>(grid[i].size()); vector<int> goldNum; for(int i=0;i<grid.size();i++) { for(int j=0;j<grid[i].size();j++) { goldNum.push_back(getGold(i,j,_flag,0)); } } sort(goldNum.begin(),goldNum.end()); return goldNum.back(); } };
After changing to reference passing, I originally thought of backtracking after calling the function recursively
int getGold(int i, int j, int totalGold) { if(i<0||j<0) return totalGold; if(i>=_grid.size()) return totalGold; if(j>=_grid[i].size()) return totalGold; if(_grid[i][j] == 0||_flag[i][j] == 1) return totalGold; _flag[i][j] = 1; vector<int> goldNumCache; // recursion goldNumCache.push_back(getGold(i-1,j,totalGold + _grid[i][j])); // to flash back if(goldNumCache.back() != totalGold + _grid[i][j]) _flag[i-1][j] = 0; // recursion goldNumCache.push_back(getGold(i+1,j,totalGold + _grid[i][j])); // to flash back if(goldNumCache.back() != totalGold + _grid[i][j]) _flag[i+1][j] = 0; // recursion goldNumCache.push_back(getGold(i,j-1,totalGold + _grid[i][j])); // to flash back if(goldNumCache.back() != totalGold + _grid[i][j]) _flag[i][j-1] = 0; // recursion goldNumCache.push_back(getGold(i,j+1,totalGold + _grid[i][j])); // to flash back if(goldNumCache.back() != totalGold + _grid[i][j]) _flag[i][j+1] = 0; sort(goldNumCache.begin(),goldNumCache.end()); return goldNumCache.back(); }
Then it's wrong
I'm still thinking about what's wrong... But I suddenly found that I don't have to think about this. It's troublesome in itself
Originally, the simplest should be to trace back when returning the function
Just mind your own state. This principle should be observed
And it does allow this, and my backtracking is reasonable after recursive calls
int getGold(int i, int j, int totalGold) { if(i<0||j<0) return totalGold; if(i>=_grid.size()) return totalGold; if(j>=_grid[i].size()) return totalGold; if(_grid[i][j] == 0||_flag[i][j] == 1) return totalGold; _flag[i][j] = 1; vector<int> goldNumCache; // recursion goldNumCache.push_back(getGold(i-1,j,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i+1,j,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j-1,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j+1,totalGold + _grid[i][j])); sort(goldNumCache.begin(),goldNumCache.end()); _flag[i][j] = 0; return goldNumCache.back(); }
Final code:
class Solution { private: vector<vector<int>> _grid; vector<vector<int>> _flag; int getGold(int i, int j, int totalGold) { if(i<0||j<0) return totalGold; if(i>=_grid.size()) return totalGold; if(j>=_grid[i].size()) return totalGold; if(_grid[i][j] == 0||_flag[i][j] == 1) return totalGold; _flag[i][j] = 1; vector<int> goldNumCache; // recursion goldNumCache.push_back(getGold(i-1,j,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i+1,j,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j-1,totalGold + _grid[i][j])); goldNumCache.push_back(getGold(i,j+1,totalGold + _grid[i][j])); sort(goldNumCache.begin(),goldNumCache.end()); _flag[i][j] = 0; return goldNumCache.back(); } public: int getMaximumGold(vector<vector<int>>& grid) { _grid = grid; _flag = vector<vector<int>>(grid.size()); for(int i=0;i<grid.size();i++) _flag[i] = vector<int>(grid[i].size()); vector<int> goldNum; for(int i=0;i<grid.size();i++) { for(int j=0;j<grid[i].size();j++) { goldNum.push_back(getGold(i,j,0)); } } sort(goldNum.begin(),goldNum.end()); return goldNum.back(); } };
Still overtime... I don't know why
After reading other people's solutions, I feel the same as mine
Others don't use flag and set grid to 0 instead. I'll try
class Solution { private: vector<vector<int>> _grid; int getGold(int i, int j, int totalGold) { if(i<0||j<0) return totalGold; if(i>=_grid.size()) return totalGold; if(j>=_grid[i].size()) return totalGold; if(_grid[i][j] == 0) return totalGold; int goldCache = _grid[i][j]; _grid[i][j] = 0; vector<int> goldNumCache; // recursion goldNumCache.push_back(getGold(i-1,j,totalGold + goldCache)); goldNumCache.push_back(getGold(i+1,j,totalGold + goldCache)); goldNumCache.push_back(getGold(i,j-1,totalGold + goldCache)); goldNumCache.push_back(getGold(i,j+1,totalGold + goldCache)); sort(goldNumCache.begin(),goldNumCache.end()); _grid[i][j] = goldCache; return goldNumCache.back(); } public: int getMaximumGold(vector<vector<int>>& grid) { _grid = grid; vector<int> goldNum; for(int i=0;i<grid.size();i++) { for(int j=0;j<grid[i].size();j++) { goldNum.push_back(getGold(i,j,0)); } } sort(goldNum.begin(),goldNum.end()); return goldNum.back(); } };
Or overtime... Thinking
Let me look at other people's solutions
Others first judge whether the next grid can go, and then call the function
I call the function first and then judge my state
I remember that it seems that calling functions also takes time, so there is inline
Let me try again
class Solution { private: static constexpr int delta[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public: int getMaximumGold(vector<vector<int>>& grid) { function<int(int,int,int)> getGold = [&](int x, int y, int totalGold) { vector<int> totalGoldCache; int goldCache = grid[x][y]; grid[x][y] = 0; // recursion for(int i=0;i<4;i++) { int nx = x + delta[i][0]; int ny = y + delta[i][1]; if((nx >= 0) && (ny >= 0) && (nx < grid.size())) if(ny < grid[nx].size()) if(grid[nx][ny] != 0) totalGoldCache.push_back(getGold(nx, ny, totalGold + goldCache)); } sort(totalGoldCache.begin(), totalGoldCache.end()); grid[x][y] = goldCache; return totalGoldCache.back(); }; vector<int> goldNum; for(int i=0;i<grid.size();i++) { for(int j=0;j<grid[i].size();j++) { if(grid[i][j] != 0) goldNum.push_back(getGold(i,j,0)); } } sort(goldNum.begin(),goldNum.end()); return goldNum.back(); } };
This will make an error... Because there may not be a value when taking the back of the vector
You also need to add a default value in advance
class Solution { private: static constexpr int delta[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public: int getMaximumGold(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); function<int(int,int,int)> getGold = [&](int x, int y, int totalGold) { vector<int> totalGoldCache; int goldCache = grid[x][y]; grid[x][y] = 0; // recursion for(int i=0;i<4;i++) { int nx = x + delta[i][0]; int ny = y + delta[i][1]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > 0) totalGoldCache.push_back(getGold(nx, ny, totalGold + goldCache)); } totalGoldCache.push_back(totalGold + goldCache); sort(totalGoldCache.begin(), totalGoldCache.end()); grid[x][y] = goldCache; return totalGoldCache.back(); }; vector<int> totalGoldCache2; for(int i=0;i<grid.size();i++) { for(int j=0;j<grid[i].size();j++) { if(grid[i][j] != 0) totalGoldCache2.push_back(getGold(i,j,0)); } } totalGoldCache2.push_back(0); sort(totalGoldCache2.begin(),totalGoldCache2.end()); return totalGoldCache2.back(); } };
That's good