面试题12,13:回溯-矩阵中的路径 -机器人的运动范围

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

思路:回溯法就是另类的暴力枚举法,从一个可行的分支下去,一直递归调用,若最后找到了符合条件的,即可
返回,若找不到,再回溯到上一层,从其他分支继续递归。如此循环。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>

using namespace std;

bool hasPath(char *matrix, int rows, int cols, char *str)
{
	if (matrix == nullptr || rows <= 0 || cols <= 0 || str == nullptr)
		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)
		{
			if (hasPathCore(matrix,rows,cols,row,col,pathLength,str,visited))
			{
				delete[] visited;//原书为什么在 返回false的时候回收 visited,而返回true的时
候,不回收?
				return true;
			}
		}
	}
	//若没有路径的情况下,需要将分配的visited数组内存释放掉。
	delete[] visited;
	return false;
}

bool hasPathCore(char *matrix, int rows, int cols, int row,int col,int &pathLength, const 
char *str,bool *visited )
{
	if (str[pathLength] == '\0')
		return true;

	bool hasPath = false;
	if (row < rows && row >= 0 && col < cols && col >= 0 && matrix[row*cols + col] == 
str[pathLength] && visited[row*cols + col] == false)
	{
		++pathLength;
		visited[row*cols + col] = true;
	}

	hasPath = hasPathCore(matrix, rows, cols, row + 1, col, pathLength, str, visited)
		|| hasPathCore(matrix, rows, cols, row - 1, col, pathLength, str, visited)
		|| hasPathCore(matrix, rows, cols, row , col+1, pathLength, str, visited)
		|| hasPathCore(matrix, rows, cols, row , col-1, pathLength, str, visited);

	if (!hasPath)
	{
		--pathLength;
		visited[row*cols + col] = false;
	}

	return hasPath;

}


int main()
{

	return 0;
}

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

思路:这题的回溯是只要遍历符合一个,便要算成功一个,和上一题的区别在于,上一题需要一直走到底,才能
判断合不合适,所以在 回溯的 Core()函数里,有一些小技巧还需要自己多去琢磨。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

int moveingCount(int threshold,int rows,int cols)
{
	bool *visited = new bool[rows * cols];
	memset(visited, 0, rows*cols);
	int count = movingCountCore(threshold,rows,cols,0,0,visited);
	delete[] visited;
	return count;
}


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 + 1, col, visited)
			+ movingCountCore(threshold, rows, cols, row - 1, col, visited)
			+ movingCountCore(threshold, rows, cols, row, col + 1, visited)
			+ movingCountCore(threshold, rows, cols, row, col-1, visited);
	}
	return count;
}
bool check(int threshold, int rows, int cols, int row, int col, bool *visited)
{
	if(row>=0 && row < rows && col>=0 && col<cols && visited[row*cols + col]==false && 
threshold >= ( getDigitSum(row)+getDigitSum(col) )   )
		return true;

	return false;
}

int getDigitSum(int num)
{
	int sum = 0;
	while (num > 0)
	{
		sum += num % 10;
		num /= 10;
	}
	return sum;
}
int main()
{


	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值