当前位置: 首页 > news >正文

Day62--图论--97. 小明逛公园(卡码网),127. 骑士的攻击(卡码网)

Day62–图论–97. 小明逛公园(卡码网),127. 骑士的攻击(卡码网)

97. 小明逛公园(卡码网)

Floyd 算法对边的权值正负没有要求,都可以处理。

方法:Floyd算法(三维版本)

思路:

动态规划五步曲:

  1. 确定dp数组含义:grid[i][j][k] = m表示 节点i 到 节点j 以k节点为中间节点的最短距离为m。(k取值自[1,k])
  2. 递推公式:
    1. 节点i 到 节点j 的最短路径经过节点k
      • 先从i走到k,再从k走到 j :grid[i][j][k] = grid[i][k][k - 1] + grid[k][j][k - 1](这里可以理解为”蹭了一下“。从全局来看,这条路是”经过了k“的。但是分成两段来看,从i到k,是不经过k的,从k到j,也是不经过k的,所以取k-1)
    2. 节点i 到 节点j 的最短路径不经过节点k
      • 不走k:grid[i][j][k] = grid[i][j][k - 1]
  3. 初始化:
  4. 遍历顺序:从递推公式看,k 依赖于 k - 1, i 和j 的到 并不依赖与 i - 1 或者 j - 1 。或者可以这么理解,i和j只是图的遍历,而k才是动态规划里面的i的遍历。所以k要在最外层for。
import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[][][] graph = new int[n + 1][n + 1][n + 1];// 初始化为不可达状态for (int i = 0; i <= n; i++) {for (int j = 0; j <= n; j++) {for (int k = 0; k <= n; k++) {// 自身到自身的距离为0if (i == j) {graph[i][j][k] = 0;} else {graph[i][j][k] = 10005;}}}}for (int i = 0; i < m; i++) {int x = in.nextInt();int y = in.nextInt();int val = in.nextInt();// 双向图graph[x][y][0] = val;graph[y][x][0] = val;}for (int k = 1; k <= n; k++) {for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {graph[i][j][k] =Math.min(graph[i][j][k - 1], graph[i][k][k - 1] + graph[k][j][k - 1]);}}}int count = in.nextInt();while (count-- > 0) {int start = in.nextInt();int end = in.nextInt();int res = graph[start][end][n];System.out.println(res == 10005 ? -1 : res);}}
}

方法:Floyd算法(二维版本)

思路:

可以看到k只依赖于k-1,与k-2,k-3等无关,所以只需要两个变量就可以了。空间上,k这一维度可以灭掉。

写完这个版本之后,观察代码,其实这就是一道很简单的动态规划题,只不过维度比普通的动态规划要多了一维,看起来恐怖了而已。

对于graph[i][j]怎么理解?

其实就是i到j怎么走?观察上层:就从i走到k,从k走到j会快一点吗?不会的话,按照原来的规划走。

import java.util.*;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[][] graph = new int[n + 1][n + 1];for (int i = 0; i <= n; i++) {for (int j = 0; j <= n; j++) {// 自身到自身的距离为0if (i == j) {graph[i][j] = 0;} else {graph[i][j] = 10005;}}}for (int i = 0; i < m; i++) {int x = in.nextInt();int y = in.nextInt();int val = in.nextInt();// 双向图graph[x][y] = val;graph[y][x] = val;}for (int k = 1; k <= n; k++) {for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {// 这里其实隐藏了一个[k-1],也就是动态规划里面的上一层。// i到j怎么走?观察上层:就从i走到k,从k走到j会快一点吗?不会的话,按照原来的规划走。graph[i][j] = Math.min(graph[i][j], graph[i][k] + graph[k][j]);}}}int count = in.nextInt();while (count-- > 0) {int start = in.nextInt();int end = in.nextInt();int res = graph[start][end];System.out.println(res == 10005 ? -1 : res);}}
}

127. 骑士的攻击(卡码网)

方法:A star算法

思路:

第一轮刷题先跳过了。远超能理解的程度。

import java.util.PriorityQueue;
import java.util.Scanner;public class Main {static int[][] moves = new int[1001][1001];static int[][] dir = {{-2, -1}, {-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}};static int b1, b2;// F = G + H// G = 从起点到该节点路径消耗// H = 该节点到终点的预估消耗static class Knight implements Comparable<Knight> {int x, y;int g, h, f;@Overridepublic int compareTo(Knight k) {  // 重载比较器,实现最小堆(按f值从小到大)return Integer.compare(this.f, k.f);}}static PriorityQueue<Knight> que = new PriorityQueue<>();static int Heuristic(Knight k) { // 欧拉距离return (k.x - b1) * (k.x - b1) + (k.y - b2) * (k.y - b2); // 统一不开根号,这样可以提高精度}static void astar(Knight k) {Knight cur, next;que.add(k);moves[k.x][k.y] = 1;  // 修正:起点需要标记为已访问,避免重复处理while (!que.isEmpty()) {cur = que.poll();if (cur.x == b1 && cur.y == b2)break;for (int i = 0; i < 8; i++) {next = new Knight();next.x = cur.x + dir[i][0];next.y = cur.y + dir[i][1];if (next.x < 1 || next.x > 1000 || next.y < 1 || next.y > 1000)continue;if (moves[next.x][next.y] == 0) {moves[next.x][next.y] = moves[cur.x][cur.y] + 1;// 开始计算Fnext.g = cur.g + 5; // 统一不开根号,这样可以提高精度,马走日,1 * 1 + 2 * 2 = 5next.h = Heuristic(next);next.f = next.g + next.h;que.add(next);}}}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();while (n-- > 0) {int a1 = scanner.nextInt();int a2 = scanner.nextInt();b1 = scanner.nextInt();b2 = scanner.nextInt();// 重置moves数组for (int i = 0; i < 1001; i++) {for (int j = 0; j < 1001; j++) {moves[i][j] = 0;}}// 清空队列(处理多组测试用例)que.clear();Knight start = new Knight();start.x = a1;start.y = a2;start.g = 0;start.h = Heuristic(start);start.f = start.g + start.h;astar(start);// 输出结果时减1,因为我们给起点加了1System.out.println(moves[b1][b2] - 1);}scanner.close();}
}
http://www.dtcms.com/a/332693.html

相关文章:

  • 嵌入式 C 语言编程规范个人学习笔记,参考华为《C 语言编程规范》
  • 使用CMAKE-GU生成Visual Studio项目
  • ​Visual Studio 2013.5 ULTIMATE 中文版怎么安装?iso镜像详细步骤
  • Pushgateway安装和部署,以及对应Prometheus调整
  • 六维力传感器:工业机器人的“触觉神经”如何突破自动化瓶颈?
  • Linux crontab定时任务
  • 3.1. CPU拓扑配置
  • 4.2 寻址方式 (答案见原书 P341)
  • Nginx蜘蛛请求智能分流:精准识别爬虫并转发SEO渲染服务
  • 嵌入式学习日记(29)进程、线程
  • Java 中 Map 接口详解:知识点与注意事项
  • HarmonyOS 实战:用 List 与 AlphabetIndexer 打造高效城市选择功能
  • Java-99 深入浅出 MySQL 并发事务控制详解:更新丢失、锁机制与MVCC全解析
  • 中小体量游戏项目主干开发的流程说明
  • 模板方法模式C++
  • 基于 Spring AI + Ollama + MCP Client 打造纯本地化大模型应用
  • Java研学-SpringCloud(三)
  • 如何安装 Homestead ?
  • 【学习笔记】JVM内存模型
  • 告别碎片化管理!飞算JavaAI实现端到端业务全流程智能监控
  • Ubuntu DNS 综合配置与排查指南
  • IP生意的天花板更高了吗?
  • 【数据分享】2022 年黑龙江省小麦、玉米和水稻幼苗影像数据集
  • Logstash 实战指南:从入门到生产级日志处理
  • GitHub 热榜项目 - 日榜(2025-08-15)
  • 硬核实用!R+贝叶斯解决真实问题:参数估计(含可靠性分析) + 回归建模(含贝叶斯因子比较) + 生产级计算实践 赠「常见报错解决方案」秘籍!
  • ubuntu 24.04 通过部署ollama提供大模型api接口
  • 线程P5 | 单例模式[线程安全版]~懒汉 + 饿汉
  • CANDB++中的CAN_DBC快速编辑方法,使用文本编辑器(如notepad++和VScode)
  • Redis 知识点与应用场景