一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
文章目录
题目一:年终奖
1.题目内容:
题目链接:年终奖
2.思路
小东只能往右或者下移动,并且每次只能移动1步:
这里可以采用动态规划的方法来做,按照动态规划的一般步骤:
- 问题:小东可以获取的最大价值
- 子问题:小东走到某个格子时的最大价值
- 状态F(i,j):小东走到(i,j)格子时的最大价值
- 转移方程:?
通过上图我们可以看到,如果小东要想在走到终点实现最大价值,那么他在到达终点前的每一步都得走的是最大价值的步。如果有一步不符合最大价值,则不符合题意。因此,我们求终点的最大价值问题就变成了求终点之前走的每一步的最大价值,因此转移方程为:
F( i , j ) = max( F( i - 1, j) , F(i,j-1)) +board[i][j] //表示到达这F( i , j )的最大价值加上本身的价值
由于第一行第一列只有一个方向到达,所以处理如下:
第一行 : F(0,j) : F(0 , j - 1)
第一列 : F(i,0):F(i - 1, 0)
3.代码实现:
import java.util.*;
public class Bonus {
public int getMost(int[][] board) {
int row = board.length;//计算行的长度
int col = board[0].length;//计算列的长度
//处理第一行
for(int i =1;i< col;i++){
board[0][i] += board[0][i-1];
}
//处理第一列
for(int i=1;i<row;i++){
board[i][0] += board[i-1][0];
}
//处理其他
for(int i =1;i< row;i++){
for(int j =1;j<col;j++){
board[i][j] += Math.max(board[i-1][j], board[i][j-1]);
}
}
return board[row-1][col-1];
}
}
题目二:迷宫问题
1.题目内容
题目链接:迷宫问题
2.思路
题目分析:
我们可以行驶的方向是上下左右都可以,但不是所有的方向都有效,比如说第一行向上走就会越界,或者遇到1的时候就会行不通。因此,我们走的是0的那条路线,并且在可能的路线中,取到达终点的最短路径。如下图,红色与蓝色路径都可到达终点,但我们要求的是红色那条,并且返回经过的所有坐标。
因为本题能走的要求:
不能越界(超出数组范围),没有障碍(只能走0的那条路),不能重复走(之前走过的路不能走了)
因此,本题采用的是回溯的思路:
假如当前位置(x,y),
- 需要判断这个位置(x,y)是否越界,(x,y)之前是否走过,(x,y)是否有障碍,如果都没有的话:
(1)把当前位置保存在路径中
(2)判断(x,y)是否是出口位置,如果是,则产生了一条新的路径。再次判断这条路径是否是最短路径,如果不是,则更新路径
(3)如果(x,y)这个位置不是出口位置,则继续搜索(x,y)的四个方向。对于搜索(x,y)的四个方向也需重复(1)(2)的判断。如果走了一圈还是回到当前路径(x,y),那么就把当前位置从路径中删除,再寻找新的路径。
3.代码
import java.util.*;
import java.io.*;
class Node{
int x;
int y;
public Node(int x,int y){
this.x = x;
this.y = y;
}
}
public class Main{
public static void main(String[] args) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str;
while((str = reader.readLine()) != null){
String[] arr = str.split(" ");
int row = Integer.parseInt(arr[0]);
int col = Integer.parseInt(arr[1]);
//创建迷宫矩阵
int[][] mat = new int[row][col];
//读入迷宫数据
for(int i = 0 ;i<row;i++){
str = reader.readLine();
arr = str.split(" ");
for(int j =0;j<col;j++){
mat[i][j] = Integer.parseInt(arr[j]);
}
}
//搜索最短路径
ArrayList<Node> path = new ArrayList<>();
ArrayList<Node> minPath = new ArrayList<>();
int [][] book = new int [row][col];
getMinPath(mat,row,col,0,0,book,path,minPath);
//打印最短路径
for(Node n: minPath){
System.out.println("(" + n.x + "," + n.y + ")");
}
}
}
/**
*
* @param mat 迷宫矩阵 row col
* @param row 行数
* @param col 列数
* @param x 当前位置
* @param y 当前位置
* @param book 标记矩阵,标记当前位置是否已经走过
* @param path 保存当前走过的每一个位置
* @param minPath 保存最短路径
*/
public static void getMinPath(int[][] mat,int row, int col,int x,
int y,int[][] book, ArrayList<Node> path,
ArrayList<Node> minPath){
//判断(x,y)是否越界了,是否走过,是否有障碍
if(x < 0|| x >= row || y < 0 || y >= col ||
book[x][y] == 1 || mat[x][y] == 1){
return;
}
//把当前位置存入路径中
path.add(new Node(x,y));
//标记当前位置
book[x][y] = 1;
//判断当前位置是否为出口
if(x == row - 1 && y == col -1){
//一条新的路径产生
//判断是否为更短的路径
if(minPath.isEmpty() || path.size() < minPath.size()){
//更新为更短的路径
minPath.clear();
for(Node n: path){
minPath.add(n);
}
}
}
//继续遍历(x,y)的上下左右四个方向
getMinPath(mat,row,col,x+1,y,book,path,minPath);
getMinPath(mat,row,col,x-1,y,book,path,minPath);
getMinPath(mat,row,col,x,y+1,book,path,minPath);
getMinPath(mat,row,col,x,y-1,book,path,minPath);
//把当前位置从路径中删除,寻找新的路径
path.remove(path.size() -1);
book[x][y] = 0;
}
}