大家好,我是晴天学长,dp版的来啦,可以是受益匪浅啊,需要的小伙伴可以关注支持一下哦!后续会继续更新的。
迷官逃脱[算法赛]
问题描述
在数学王国中,存在- -个大小为N x M的神秘迷言。第i行第j个位置坐标为(i,j),每个位置(i;,j) (1≤i≤N,1≤j≤M)都对应着一个正整数Aij。迷宫的左上角坐标为(1,1), 右下角坐标为(N,M)。
小蓝初始位于坐标(1,1),并携带著Q把密匙。他的目标是移动到迷言的终点,即坐标(N, M)处。但是通往迷宫尽头的道路并不是一-帆风顺的, 在前进的过程中,他遇到了一些奇特的规则。
规则如下:
1.小蓝每次只能向右移动一个位置或向下移动一个位置。
2.当小蓝所在位置的数和下一步移动位置的数互质时,会有一扇封闭的铁门, 小蓝需要消耗-把密匙来打开铁门,打开铁门后,这把钥匙将被摧毁。如果没有密匙,小蓝将无法移动到该位置。
你需要输出小蓝从起点到终点路径之和的最大值,如果无法从起点到达终点,输出-1
。
输入格式
第一行输入包含3个整数N, M, Q,分别为迷言的大小和密匙的数量。
接下来输入N行,每行M个整数,为迷言上的数值。
输出格式
输出仅一-行,包含-个整数,表示管案。
样例输入
331
139
样例输出
28
迷宫逃脱(DP版)
1.用快读快输接收数据。
2.建立矩阵
3.打表,建立一个三维的dp表。
4.状态转移方程
1.从上面来
int floor=
2.从左面来
int right=
3.状态转移方程
dp[i][j][k] = Math.,max();
4.输出dp[n][m][k](带循环)。
1.读取输入的N、M和Q的值(迷宫的尺寸和最大钥匙数量)。
2.创建一个名为"grid"的二维网格数组,用于存储迷宫中每个单元格的值。
3.初始化动态规划数组"dp",其维度为[1100][1100][4],用于存储不同钥匙数量下每个位置的最大分数。
4.读取迷宫中每个单元格的值,并将其存储在"grid"数组中。
5.在"dp"数组中设置起始位置(1, 1)的初始值。因为它是起始位置,所以分数等于该单元格的值。
6.开始动态规划过程,遍历迷宫中的每个单元格。
7.找到最后一行和最后一列的单元格中不同钥匙数量下的最大分数。
8.将最大分数作为结果进行打印输出。如果最大分数小于或等于0,则输出-1。
9.刷新输出。
package LanQiaoTest.动态规划;
import jdk.swing.interop.SwingInterOpUtils;
import java.io.*;
public class 迷宫逃脱_DP {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static long dp[][][] = new long[1100][1100][4];
static String[] lines;
public static void main(String[] args) throws IOException {
lines = in.readLine().split(" ");
int N = Integer.parseInt(lines[0]);
int M = Integer.parseInt(lines[1]);
int Q = Integer.parseInt(lines[2]);
long[][] grid = new long[N + 10][M + 10];
// 接收数据
for (int i = 1; i <= N; i++) {
lines = in.readLine().split(" ");
for (int j = 1; j <= M; j++) {
grid[i][j] = Integer.parseInt(lines[j - 1]);
}
}
//起点赋初值(因为起点没有上一个的状态,自己就是自己)
for (int i = 0; i <= Q; i++) {
dp[1][1][i] = grid[1][1];
}
//开始打表
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
for (int k = 0; k <= Q; k++) {
int floor = gcd((int) grid[i][j], (int) grid[i][j - 1]) == 1 ? 1 : 0;
int left = gcd((int) grid[i][j], (int) grid[i - 1][j]) == 1 ? 1 : 0;
//注意钥匙不能超了
//上面来
//是质数,必须有钥匙。
if (k - floor >= 0 && dp[i][j - 1][k - floor] != 0) {
dp[i][j][k] = Math.max(dp[i][j][k], dp[i][j - 1][k - floor] + grid[i][j]);
}
//左面来,注意更新最大值
if (k - left >= 0 && dp[i - 1][j][k - left] != 0) {
dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j][k - left] + grid[i][j]);
}
}
}
}
//找到终点的最大值
long result = 0;
for (int i = 0; i <= Q; i++) {
result = Math.max(result, dp[N][M][i]);
}
out.println(result <= 0 ? -1 : result);
out.flush();
}
private static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}
试题链接: