《剑指Offer——12.矩阵中的路径,13.机器人的运动范围》代码

Posted 穿迷彩服的鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指Offer——12.矩阵中的路径,13.机器人的运动范围》代码相关的知识,希望对你有一定的参考价值。


前言

//==================================================================
// 《剑指Offer——12.矩阵中的路径,13.机器人的运动范围》代码
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H
// =================================================================
// 题目:地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动,它
// 每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和
// 大于k的格子。例如,当k为18时,机器人能够进入方格(35, 37),因为3+5+3+7=18。
// 但它不能进入方格(35, 38),因为3+5+3+8=19。请问该机器人能够到达多少个格子?
//==================================================================


一、示例

1.矩阵中的路径

/*********************************************************************
/*
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”
单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
*/
***********************************************************************/

2.机器人的运动范围

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

示例 1
输入:m = 2, n = 3, k = 1
输出:3
 4 3 4
[(0,0)(0,1)(0,2)]
[(1,0)(1,1)(1,2)]
[(2,0)(2,1)(2,2)]
[(3,0)(3,1)(3,2)]
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
*/
***********************************************************************/

二、代码解析

1.新建.cpp文件

代码如下(示例):

//==================================================================
// 《剑指Offer——12.矩阵中的路径,13.机器人的运动范围》代码
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H
// =================================================================
// 题目:地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动,它
// 每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和
// 大于k的格子。例如,当k为18时,机器人能够进入方格(35, 37),因为3+5+3+7=18。
// 但它不能进入方格(35, 38),因为3+5+3+8=19。请问该机器人能够到达多少个格子?
//==================================================================

#include <iostream>
#include<vector>
using namespace std;

/*
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”
单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:
输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
*/
/*回溯*/
bool hasPath(vector<vector<char>>& board, int row, int col, int rows, int cols, string word, int k)
{
	if (row < 0 || row >= rows || col < 0 || col >= cols || board[row][col] != word[k])
	{
		return false;
	}
	if (k == word.size() - 1)
	{
		return true;
	}
	board[row][col] = '\\0';
	bool res = hasPath(board, row + 1, col, rows, cols, word, k + 1) ||
		hasPath(board, row, col + 1, rows, cols, word, k + 1) ||
		hasPath(board, row - 1, col, rows, cols, word, k + 1) ||
		hasPath(board, row, col - 1, rows, cols, word, k + 1);
	board[row][col] = word[k];
	return res;
}

bool exist(vector<vector<char>>& board, string word)
{
	if (board.empty() || word.empty())
	{
		return false;
	}

	int rows = board.size();
	int cols = board[0].size();
	int k = 0;
	for (int row = 0; row < rows; ++row)
	{
		for (int col = 0; col < cols; ++col)
		{
			if (hasPath(board, row, col, rows, cols, word, k))
			{
				return true;
			}
		}
	}

	return false;
}




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

示例 1
输入:m = 2, n = 3, k = 1
输出:3
 4 3 4
[(0,0)(0,1)(0,2)]
[(1,0)(1,1)(1,2)]
[(2,0)(2,1)(2,2)]
[(3,0)(3,1)(3,2)]
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
*/
/*法一----回溯*/
int getDigitSum(int number)
{
	int sum = 0;
	while (number > 0)
	{
		sum += number % 10;
		number /= 10;
	}

	return sum;
}

bool check(int k, int rows, int cols, int row, int col, vector<vector<bool>>& visited)
{
	if (row >= 0 && row < rows && col >= 0 && col < cols
		&& getDigitSum(row) + getDigitSum(col) <= k && !visited[row][col])
	{
		return true;
	}

	return false;
}

int movingCountCore(int k, int rows, int cols, int row, int col, vector<vector<bool>>& visited)
{
	int count = 0;
	if (check(k, rows, cols, row, col, visited))
	{
		visited[row][col] = true;
		count = 1 + movingCountCore(k, rows, cols, row - 1, col, visited) +
			movingCountCore(k, rows, cols, row + 1, col, visited) +
			movingCountCore(k, rows, cols, row, col - 1, visited) +
			movingCountCore(k, rows, cols, row, col + 1, visited);
	}
	return count;
}
int movingCount1(int m, int n, int k)
{
	if (m <= 0 || n <= 0 || k < 0)
	{
		return 0;
	}
	vector<vector<bool>> visited(m, vector<bool>(n, false));

	int count = movingCountCore(k, m, n, 0, 0, visited);

	return count;
}

/*法二----递推*/
int movingCount2(int m, int n, int k)
{
	if (!k)return 1;
	if (m <= 0 || n <= 0 || k < 0)return 0;
	vector<vector<int>> visited(m, vector<int>(n, 0));
	int res = 0;
	visited[0][0] = 1;
	for (int i = 0; i < m; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if (getDigitSum(i) + getDigitSum(j) > k)continue;
			if (i - 1 >= 0)
			{
				visited[i][j] |= visited[i - 1][j];
			}
			if (j - 1 >= 0)
			{
				visited[i][j] |= visited[i][j - 1];
			}

			res += visited[i][j];
		}
	}

	return res;
}
int main()
{
	vector<vector<char>> board =
	{
		{ 'A', 'B','C', 'E'},
		{ 'S', 'F', 'C', 'S'},
		{ 'A', 'D', 'E', 'E'}
	};
	string word = "ABCCED";
	cout << "《剑指Offer——12.矩阵中的路径》代码" << endl;
	cout << exist(board, word) << endl << endl;

	cout << "剑指 Offer 13. 机器人的运动范围" << endl;
	cout << "法一----回溯" << movingCount1(16, 8, 4) << endl;
	cout << "法二----递推" << movingCount2(16, 8, 4) << endl;
	return 0;
}

三,测试

以上是关于《剑指Offer——12.矩阵中的路径,13.机器人的运动范围》代码的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer13,机器人的运动范围(和矩阵路径很像)

java刷题-剑指offer 12 矩阵中的路径

剑指 Offer(C++版本)系列:剑指 Offer 12 矩阵中的路径

剑指 Offer(C++版本)系列:剑指 Offer 12 矩阵中的路径

剑指 Offer(C++版本)系列:剑指 Offer 12 矩阵中的路径

算法剑指 Offer 12. 矩阵中的路径