您的位置:首页 > Web前端

【剑指offer】第十二题(矩阵中的路径)和 第十三题(机器人的运动范围)

2018-03-18 13:03 495 查看
第十二题:矩阵中的路径

题目:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所ga有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以以在矩阵中向左、右、下、上移动一格。如果一条l路经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的 3*4 的矩阵中包含了一条字符串  "bfce" 的 路径(路径中的字母用下划线标出)。但矩阵中不包含字符串 “abfb” 的路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

char matrix[3][4] = {
{'a','b','t','g'},
{'c','f','c','s'},
{'j','d','e','h'}
};
char str[] = "bfce";

解题程序:

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;

//此函数,用来判断当前路径满足的条件下,相邻格子是存在一个格子满足条件
bool hasPathCore(const char *matrix,int rows,int cols,int row,int col,char *str,int &pathLength,bool *visited)
{
// 如果目标路径中的所有格子都已经被遍历完,则返回 true
if(str[pathLength] == '\0')
return true;
bool hasPath = false;

// 如果找到一个满足条件的路径的格子
if(row>=0 && row<rows && col>=0 && col<cols && matrix[row*cols+col] == str[pathLength] && !visited[row*cols+col])
{
// 目标路径的格子向后移动一格
++pathLength;
// 通过辅助矩阵标记,此格子已经被访问过,下次不能再次被访问。
visited[row*cols+col] = true;

// 如果矩阵格子(row,col) 与路径字符串下标为 pathLength 的字符一样时,从它的4个相邻格子中寻找与路径字符串
// 下标为 pathLength+1 的字符串相等的格子

hasPath = hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited) ||             // 判断左边格子
hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited) ||             // 判断右边格子
hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited) ||             // 判断上方格子
hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited);               // 判断下方格子

// 如果没有找到,则说明当前第 pathLength 个字符定位不确定,返回上一个位置,重新定位
if(!hasPath)
{
--pathLength;
visited[row*cols+col] = false;
}
}
return hasPath;
}

// 判断任意一个坐标中的值是否是路径中的一个数值

bool hasPath(const char*matrix,int rows,int cols,char *str)
{
// 边界检查,检测下标是否越界
if( matrix == NULL || rows<1 || cols<1 || str == NULL )
{
return false;
}

// 动态申请一个辅助矩阵,来标记路径是否已经进入了格子
bool *visited = new bool[rows*cols];

// 给辅助矩阵初始化,清空
memset(visited,0,rows*cols);

int pathLength = 0;

// 循环的目的是为了实现从矩阵中随机出发,寻找路径
for(int row = 0;row<rows;row++)
{
for(int col = 0;col<cols;col++)
{
printf("row = %d,col = %d\n",row,col);
if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visited))
return true;
}

}

// 释放动态分配的内存空间
delete []visited;
visited = NULL;

return false;
}

int main(void)
{
char matrix[3][4] = {{'a','b','t','g'},
{'c','f','c','s'},
{'j','d','e','h'}
};

//const char *matrix1 = "abtgcfcsjdeh";
char str[] = "bfce";

bool res = hasPath((const char*)matrix,3,4,str);

cout<<res<<endl;

return 0;
}


第十三题:机器人的运动范围
题目:

地上有一个 m 行 n 列的方格。一个机器人从坐标 (0,0) 的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于 k 的格子。例如:当 k 为 18 时,机器人能够进入方格 (35,37),因为,3+5+3+7 = 18。但不能进入方格 (35,18),因为, 3+5+3+8=19,请问 机器人能够到达多少个格子?

解题程序:

#include<iostream>
#include<stdio.h>
using namespace std;

// 计算格子的行和列的值是 <= threshold

int getDigitSum(int num)
{
int sum = 0;

while(num>0)
{
sum += num%10;     // 先给 sum 加上 num 数字的个位
num = num/10;      // 获取 num 的十位数字
}

return sum;
}

// 检测相邻格子是否符合要求
bool check(int threshold,int rows,int cols,int row,int col,bool *visited)
{
if( row>=0 && row<rows && col>=0 && col<cols && getDigitSum(row)+getDigitSum(col)<= threshold && !visited[row*cols+col])
{
return true;
}
return false;
}

// 计算有多少个格子符合题目要求
int movingCountCore(int threshold,int rows,int cols,int row,int col,bool *visited)
{
int count = 0;

if(check(threshold,rows,cols,row,col,visited))
{
visited[row*cols + col] = true;

count = 1 + movingCountCore(threshold,rows,cols,row,col-1,visited)        // 判断当前格子的左边是否符合条件
+ movingCountCore(threshold,rows,cols,row,col+1,visited)        // 判断当前格子的右边是否符合条件
+ movingCountCore(threshold,rows,cols,row-1,col,visited)        // 判断当前格子的上边是否符合条件
+ movingCountCore(threshold,rows,cols,row+1,col,visited);       // 判断当前格子的下边是否符合条件

}

// 返回符合条件的格子数量
return count;
}

int movingCount(int threshold,int rows,int cols)
{
// 边界值检测
if(threshold <0 || rows<= 0 || cols<= 0)
{
return 0;
}

// 动态申请辅助矩阵
bool *visited = new bool[rows*cols];

// 给刚刚申请的矩阵赋初值  false

for(int i = 0; i<rows*cols; i++)
{
visited[i] = false;
}

int count = movingCountCore(threshold,rows,cols,0,0,visited);

delete []visited;
visited = NULL;

return count;
}

// 测试用例:

void test()
{
int m;
int n;
int k;
scanf("%d%d%d",&k,&m,&n);

int res = movingCount(k,m,n);
printf("res = %d\n",res);
}

int main(void)
{
test();

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: