剪枝&回溯
剑12 矩阵中的路径@@
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
示例 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
分析:经典回溯,但此题只要求返回true or false,能返回所有路径吗?
friend ostream &operator<<(ostream &out, const vector<vector<char>> &board)
{
//重载 << ,用于调试输出二维数组
for (auto i : board)
{
for (auto j : i)
{
out << j << " ";
}
out << endl;
}
out << endl;
return out;
}
bool backtrack(vector<vector<char>> &board, int row, int col,
const string &word, int idx)
{
//正确返回终止条件,找到一个正确分支即终止
if (idx == word.size())
return true;
//数组越界终止条件
if (row < 0 || row >= board.size() ||
col < 0 || col >= board[0].size())
return false;
//如果表格当前字符不等于欲匹配字符,剪掉此分支
//这样还在增长的分支就是可能正确的分支
if (word[idx] != board[row][col])
return false;
//设置标记位,如果后续回到此位置,比对字符即知
board[row][col] = '*';
//往四个方向走,有一个方向返回true,程序返回true
if (backtrack(board, row - 1, col, word, idx + 1) ||
backtrack(board, row + 1, col, word, idx + 1) ||
backtrack(board, row, col - 1, word, idx + 1) ||
backtrack(board, row, col + 1, word, idx + 1))
return true;
//回溯。走不通时该位置还原为本来的字母
board[row][col] = word[idx];
//cout<<board;
//没有分支返回true。程序返回false
return false;
}
bool exist(vector<vector<char>> &board, string word)
{
if (board.empty() || board[0].empty())
return word.empty();
for (int row = 0; row < board.size(); ++row)
{
for (int col = 0; col < board[0].size(); ++col)
{
//暴力搜索每一点作为起点
if (backtrack(board, row, col, word, 0))
return true;
}
}
return false;
};
剑13.机器人的运动范围
地上有一个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
示例 1:
输入:m = 3, n = 1, k = 0
输出:1
第一版代码
根据上面一题直接写出此题的代码,提交结果为超时,本地运行超时用例时等待很久,说明有死循环。本着“不放弃每一段代码”的精神,我决定debug后再看书上的答案
class Solution {
public:
int K;
friend ostream &operator<<(ostream &