给定一个 m x n 的整数矩阵 mat
,我们需要找出从某个单元格出发可以访问的最大单元格数量。移动规则是可以从当前单元格移动到同一行或同一列的任何其他单元格,但目标单元格的值必须严格大于当前单元格的值。需要返回最大可访问的单元格数量。
输入:mat = [[3,1],[3,4]]
输出:2
解释:从第 1 行、第 2 列的单元格开始,可以访问 2 个单元格。
输入:mat = [[1,1],[1,1]]
输出:1
解释:由于目标单元格必须严格大于当前单元格,只能访问 1 个单元格。
输入:mat = [[3,1,6],[-9,5,7]]
输出:4
解释:从第 2 行、第 1 列的单元格开始,可以访问 4 个单元格。
m == mat.length
n == mat[i].length
1 <= m, n <= 10^5
1 <= m * n <= 10^5
-10^5 <= mat[i][j] <= 10^5
采用深度优先搜索(DFS)结合动态规划(DP)来解决此问题。用 dp[i][j]
表示从位置 (i, j)
出发可以访问的最大单元格数。
#include
#include
#include
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int matSize, matColSize;
int **mat, **dp;
bool isValid(int x, int y) {
return x >= 0 && x < matSize && y >= 0 && y < matColSize;
}
int dfs(int x, int y) {
if (dp[x][y] != 0) return dp[x][y];
int maxLen = 1;
for (int col = 0; col < matColSize; col++) {
if (col != y && mat[x][col] > mat[x][y]) {
maxLen = MAX(maxLen, 1 + dfs(x, col));
}
}
for (int row = 0; row < matSize; row++) {
if (row != x && mat[row][y] > mat[x][y]) {
maxLen = MAX(maxLen, 1 + dfs(row, y));
}
}
dp[x][y] = maxLen;
return maxLen;
}
int maxIncreasingCells(int** matrix, int matrixSize, int* matrixColSize){
mat = matrix;
matSize = matrixSize;
matColSize = *matrixColSize;
dp = (int**)calloc(matSize, sizeof(int*));
for (int i = 0; i < matSize; i++) {
dp[i] = (int*)calloc(matColSize, sizeof(int));
}
int maxCells = 0;
for (int i = 0; i < matSize; i++) {
for (int j = 0; j < matColSize; j++) {
maxCells = MAX(maxCells, dfs(i, j));
}
}
for (int i = 0; i < matSize; i++) {
free(dp[i]);
}
free(dp);
return maxCells;
}
读取输入矩阵,并初始化 dp
数组。dp[i][j]
用于存储从位置 (i, j)
出发可以访问的最大单元格数。
int matSize, matColSize;
int **mat, **dp;
dp = (int**)calloc(matSize, sizeof(int*));
for (int i = 0; i < matSize; i++) {
dp[i] = (int*)calloc(matColSize, sizeof(int));
}
检查从当前单元格移动到目标单元格是否合法,即目标单元格的值必须严格大于当前单元格的值。
bool isValid(int x, int y) {
return x >= 0 && x < matSize && y >= 0 && y < matColSize;
}
dp[x][y]
已计算,直接返回。dp[x][y]
。int dfs(int x, int y) {
if (dp[x][y] != 0) return dp[x][y];
int maxLen = 1;
// 遍历同一行中的其他单元格
for (int col = 0; col < matColSize; col++) {
if (col != y && mat[x][col] > mat[x][y]) {
maxLen = MAX(maxLen, 1 + dfs(x, col));
}
}
// 遍历同一列中的其他单元格
for (int row = 0; row < matSize; row++) {
if (row != x && mat[row][y] > mat[x][y]) {
maxLen = MAX(maxLen, 1 + dfs(row, y));
}
}
dp[x][y] = maxLen;
return maxLen;
}
int maxIncreasingCells(int** matrix, int matrixSize, int* matrixColSize){
mat = matrix;
matSize = matrixSize;
matColSize = *matrixColSize;
dp = (int**)calloc(matSize, sizeof(int*));
for (int i = 0; i < matSize; i++) {
dp[i] = (int*)calloc(matColSize, sizeof(int));
}
int maxCells = 0;
// 遍历每个单元格
for (int i = 0; i < matSize; i++) {
for (int j = 0; j < matColSize; j++) {
maxCells = MAX(maxCells, dfs(i, j));
}
}
for (int i = 0; i < matSize; i++) {
free(dp[i]);
}
free(dp);
return maxCells;
}
dp
数组。我尽力了。。。不愧是困难提题目
#include
#include
#include
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int gotoNext(int** dp, int matSize, int* matColSize, int** mat, int beginCol, int beginRow, int* tmpStepCnt, bool** isVisited)
{
if(dp[beginCol][beginRow] != 0)
{
(*tmpStepCnt) += dp[beginCol][beginRow];
return (*tmpStepCnt);
}
(*tmpStepCnt)++;
isVisited[beginCol][beginRow] = true;
int tmp_left = 0, tmp_right = 0, tmp_up = 0, tmp_down = 0;
int left = 0, right = 0, up = 0, down = 0;
int cnt = 0;
for (int i = 1; i < matSize; i++)
{
if(beginCol + i <= matSize - 1 && !isVisited[beginCol + i][beginRow] && mat[beginCol + i][beginRow] > mat[beginCol][beginRow])
{
tmp_right = gotoNext(dp, matSize, matColSize, mat, beginCol + i, beginRow, &cnt, isVisited);
right = MAX(tmp_right, right);
cnt = 0;
// printf("right = %d\n",right);
}
else
{
// // printf("cant goto [%d][%d]\n",beginCol + i, beginRow);
}
if(beginCol - i >= 0 && !isVisited[beginCol - i][beginRow] && mat[beginCol - i][beginRow] > mat[beginCol][beginRow])
{
tmp_left = gotoNext(dp, matSize, matColSize, mat, beginCol - i, beginRow, &cnt, isVisited);
left = MAX(tmp_left, left);
cnt = 0;
// printf("left = %d\n",left);
}
else
{
// // printf("cant goto [%d][%d]\n",beginCol - i, beginRow);
}
}
for (int i = 1; i < (*matColSize); i++)
{
if(beginRow + i <= (*matColSize) - 1 && !isVisited[beginCol][beginRow + i] && mat[beginCol][beginRow + i] > mat[beginCol][beginRow])
{
tmp_down = gotoNext(dp, matSize, matColSize, mat, beginCol, beginRow + i, &cnt, isVisited);
down = MAX(tmp_down, down);
cnt = 0;
// printf("down = %d\n",down);
}
else
{
// // printf("cant goto [%d][%d]\n",beginCol, beginRow + i);
}
if(beginRow - i >= 0 && !isVisited[beginCol][beginRow - i] && mat[beginCol][beginRow - i] > mat[beginCol][beginRow])
{
tmp_up = gotoNext(dp, matSize, matColSize, mat, beginCol, beginRow - i, &cnt, isVisited);
up = MAX(tmp_up, up);
cnt = 0;
// printf("up = %d\n",up);
}
else
{
// // printf("cant goto [%d][%d]\n",i, beginRow - i);
}
}
isVisited[beginCol][beginRow] = false;
(*tmpStepCnt) += MAX(MAX(left, right), MAX(up, down));
return (*tmpStepCnt);
}
int maxIncreasingCells(int** mat, int matSize, int* matColSize){
int stepCnt = 0;
int **dp = (int**)calloc(matSize, sizeof(int*)); // 记录从某个格子开始走,可以走多少个格子。
bool **isVisited = (bool**)calloc(matSize, sizeof(bool*)); // 记录某个格子是否被访问,防止死循环。
for (int i = 0; i < matSize; i++)
{
dp[i] = (int*)calloc((*matColSize), sizeof(int)); // 记录从某个格子开始走,可以走多少个格子。
isVisited[i] = (bool*)calloc((*matColSize), sizeof(bool)); // 记录某个格子是否被访问,防止死循环。
}
for (int i = 0; i < matSize; i++)
{
for (int j = 0; j < (*matColSize); j++)
{
int tmpStepCnt = 0;
tmpStepCnt = gotoNext(dp, matSize, matColSize, mat, i, j, &tmpStepCnt, isVisited);
stepCnt = MAX(tmpStepCnt, stepCnt);
dp[i][j] = tmpStepCnt;
// printf("dp[%d][%d] = %d\n", i,j,dp[i][j]);
}
}
return stepCnt;
}
这个更惨,