[C + +] backtracking method uses reference passing, lambda expression, vector Back() use

Posted by Jyotsna on Sat, 05 Feb 2022 19:31:11 +0100

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)
if(i>=_grid.size())
if(j>=_grid[i].size())

if(_grid[i][j] == 0||flagCache[i][j] == 1)

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)
if(i>=_grid.size())
if(j>=_grid[i].size())

if(_grid[i][j] == 0||_flag[i][j] == 1)

_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)
if(i>=_grid.size())
if(j>=_grid[i].size())

if(_grid[i][j] == 0||_flag[i][j] == 1)

_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)
if(i>=_grid.size())
if(j>=_grid[i].size())

if(_grid[i][j] == 0||_flag[i][j] == 1)

_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)
if(i>=_grid.size())
if(j>=_grid[i].size())

if(_grid[i][j] == 0)

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;

};

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;

};

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());