今天这两道题,真的不太懂,基础知识不太牢固,得去补补了,尽力理解,实在理解不下来,背,背,我都要背下来,加油~~
package com.sorrymaker.day3814; import org.junit.Test; /** * 地上有一个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。请问该机器人能够到达多少个格子? * @Author nextGame * @Date 2021/8/25 21:18 * @Version 1.0 */ public class MovingCount { // 棋盘的行列 int m, n; // 记录位置是否被遍历过 boolean[][] visited; @Test public void test(){ System.out.println(movingCount(3, 3, 2)); } public int movingCount(int m, int n, int k) { this.m = m; this.n = n; visited = new boolean[m][n]; return dfs(0, 0, k); } private int dfs(int i, int j, int k) { // i >= m || j >= n是边界条件的判断 if (i >= m || j >= n // visited[i][j]判断这个格子是否被访问过 || visited[i][j] == true // k < sum(i, j)判断当前格子坐标是否满足条件 || k < sum(i, j)) { //当数组越界,或者被访问过,或者是不满住sum(i,j)的条件的话, 就返回0,不计入可达解总数中。 return 0; } // 标注这个格子被访问过 visited[i][j] = true; // 沿着当前格子的右边和下边继续访问 //返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。 return 1 + dfs(i + 1, j, k) + dfs(i, j + 1, k); } // 计算两个坐标数字的和 private int sum(int i, int j) { int sum = 0; while (i != 0) { sum += i % 10; i /= 10; } while (j != 0) { sum += j % 10; j /= 10; } return sum; } }
package com.sorrymaker.day3814; /** * 矩阵中的路径 * DFS + 剪枝 , 真看不懂,要慢慢消化。。。 * @Author nextGame * @Date 2021/8/25 20:50 * @Version 1.0 */ public class ExistsWords { public boolean exist(char[][] board, String word) { char[] words = word.toCharArray(); //一个一个字母来尝试,每一次尝试都是dfs遍历成功的一种可能性 for(int i = 0; i < board.length; i++) { for(int j = 0; j < board[0].length; j++) { if (dfs(board, words, i, j, 0)) { return true; } } } //遍历完成,仍没有成功的路径,返回False return false; } // board:网格, i:当前行, j:当前列, word:待匹配字符串, k:当前匹配到字符串word的位置 boolean dfs(char[][] board, char[] word, int i, int j, int k) { // 用来判断程序是否越界,还有第一个字母是否匹配,第一个都不匹配直接返回False // 1. 下标越界,2. 当前位置与word中字符不匹配,则可以直接返回(剪枝) if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) { return false; } //当程序跑到word的最后一个字母时,这时无需再dfs,直接返回True //说明word中的字符全部被匹配 if(k == word.length - 1) { return true; } //把访问过的字母标记为空,这样可以避免程序多次访问同一元素 // 使用board数组充当了访问标记数组,节省了空间(非常妙!)??? board[i][j] = '\0'; //剪枝顺序:左、右、下、上 boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1); //一趟dfs结束后把原来设的空改回来,以免影响后面的dfs遍历使用 board[i][j] = word[k]; return res; } }