剑指offer--机器人的活动范围 回溯法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanani_Jia/article/details/82807673

题目描述

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

  写这道题的时候了解到了一个新的方法叫做回溯法,回溯法也称之为试探法,用这个方法的前提就是我们牺牲了一定的时间复杂度,所以如果要是有的问题限制时间来求解那就不适合用这种方法,回溯法将问题的候选解按照某一个指定的顺序逐一去枚举和检验,当发现现在的解不是我们要的那个解时,就去寻找下一个候选解,如果当前候选解都不满足要求是就扩大当前候选解的规模,并且继续去试探,如果找到了符合条件的答案,那当前候选解就是问题的一个答案,在这个方法中,放弃当前候选解,寻找下一个候选解的过程称之为回溯。其实回溯就是我们经常所说的暴力求解的方法,我们把当前问题的所有可能解都列出来一个一个去试看哪个解是满足我们当前问题的。

class Solution {

public:

int movingCount(int threshold, int rows, int cols)

{

bool *robot = new bool [rows*cols];

for (int i = 0; i < rows*cols; i++)

{

robot[i] = false;

}

int count = Moving(threshold, rows, cols, 0, 0, robot);

delete[] robot;

return count;

    

}

int Moving(int k, int rows, int cols, int left, int right, bool *robot)

{

int count = 0;

if(GetTorF(k, rows, cols, left, right,robot))

{

robot[left*cols + right] = true;

count = 1 + Moving(k, rows , cols, left-1, right, robot)

+ Moving(k, rows , cols, left+1, right, robot)

+ Moving(k, rows, cols , left, right-1, robot)

+ Moving(k, rows, cols , left, right+1, robot);

}

return count;

}

bool GetTorF(int k, int rows, int cols, int left, int right, bool *robot)

{

int sumleft = Getnum(left);

int sumright = Getnum(right);

if (left>=0&&right>=0&&left <= rows&&right <= cols&&sumleft +sumright <= k&&robot[left*cols+right]==false)

return true;

else

return false;

}

int Getnum(int n)

{

int sum = 0;

while (n >0)

{

sum += n % 10;

n = n / 10;

}

return sum;

}

};

这里我们用了4个函数来解决这个问题,这里不得不把某些功能提出来变成一个函数,我本身是特别不喜欢多写函数的...一个函数能解决的就解决。

我们这里用递归的方法去遍历我们创建的bool数组,bool数组中的数据全都是false,如果我们这个位置符合条件,那我们就把这个位置的值变成我们true。

int Moving(int k, int rows, int cols, int left, int right, bool *robot)

{

int count = 0;

if(GetTorF(k, rows, cols, left, right,robot))

{

robot[left*cols + right] = true;

count = 1 + Moving(k, rows , cols, left-1, right, robot)

+ Moving(k, rows , cols, left+1, right, robot)

+ Moving(k, rows, cols , left, right-1, robot)

+ Moving(k, rows, cols , left, right+1, robot);

}

return count;

}

这是我们的递归函数,这个函是可以和我们的初始函数变成一个的,不过我还是拿出来了,这里count的值就是我当前符合不符合,我符合的话就去算我周围上下左右的四个值看看符合不符合。这和我们之前所接触的迷宫问题类似,我走到当前这个位置的时候去看我周围四个地方哪个可以动。

bool GetTorF(int k, int rows, int cols, int left, int right, bool *robot)

{

int sumleft = Getnum(left);

int sumright = Getnum(right);

if (left>=0&&right>=0&&left <= rows&&right <= cols&&sumleft +sumright <= k&&robot[left*cols+right]==false)

return true;

else

return false;

}

int Getnum(int n)

{

int sum = 0;

while (n >0)

{

sum += n % 10;

n = n / 10;

}

return sum;

}

通过第一个函数来判断我们这个位置到底能不能走,也就是这个位置是不是符合我们题目中所给的条件。通过第二个函数来计算我们对应位置的每个数位相加的和,因为这是个while循环所以不得不把他提出来变成一个函数。

 这道题并不难,不过还是不知道怎么去下手浪费很多时间,遇到问题要一步一步来就可以了。

 之后给大家分享我们的选择题:

哈弗曼编码是一种无损二进制熵编码算法,其加权路径长度最小,字符串“alibaba”的二进制哈弗曼编码有___位(bit)

A.11

B.12

C.13

D.14

今天我们要介绍的哈夫曼,哈夫曼树很早之前就接触过了,现在甚至都忘了是个什么了,今天看这个题即使是知道哈夫曼树是个啥估计也写不出来,不知道题目在说些什么,这里我们简单介绍一下思路。

先看题目给我们的字符串alibaba,这其中a出现了3次,l出现了1次,i出现了1次,b出现了2次,所以就根据字母出现的权重来设计我们的哈弗曼树。

3,2,1,1,四个数字来画哈夫曼树。

最小的肯定在最底层然后让2,2,3三个数字来画

就变成了这样之后就是4,3去画了。

这最终我们的树就画成了。这时候去求我们的哈夫曼编码有多少位,分别是1*3+1*3+2*2+3*1=13选C

这里再多说一句,哈夫曼编码是我们的哈夫曼树里边左为0,右为1,像上图l编码就是000,i的就是001,b就是01,a就是1.整个字符串就是000001011.

 

猜你喜欢

转载自blog.csdn.net/Hanani_Jia/article/details/82807673