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

代码随想录算法训练营第六十天 | 图 | A星算法

Day 60 总结

  • 自己实现中遇到哪些困难
  • 今日收获,记录一下自己的学习时间
    • 13:00 - 14:00

BFS

题目:127. 骑士的攻击

给定两个坐标,搜索最短路径

使用 BFS,广度搜索,按层搜索找到最短路径

public class Main {
    public static void main(String[] args) {
        new Main().solve();
    }

    public void solve() {
        Scanner sc = null;
        try {
             sc = new Scanner(new File("1.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        int n = sc.nextInt();
        for (int i=0; i<n; i++) {
            int a1 = sc.nextInt();
            int a2 = sc.nextInt();
            int b1 = sc.nextInt();
            int b2 = sc.nextInt();
            bfs(a1,a2,b1,b2);
        }

    }

    public void bfs(int a1, int a2, int b1, int b2) {
        int[][] dir = {{-2,-1}, {-2,1}, {-1,2}, {1,2}, {2,1}, {2,-1}, {1,-2}, 
        {-1,-2},};

        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{a1,a2});
        int[][] moves = new int[1001][1001];// 1000 * 1000的棋盘

        while (!queue.isEmpty()) {
            int[] pos = queue.poll();
            int x = pos[0];
            int y = pos[1];
            if (x == b1 && y == b2) break;

            for (int i=0; i<8; i++) {
                int xx = x+dir[i][0];
                int yy = y+dir[i][1];
                if (xx >= 1 && xx <= 1000 && yy >= 1 && yy <= 1000 && moves[xx][yy]==0) {
                    queue.add(new int[]{xx, yy});
                    moves[xx][yy] = moves[x][y] + 1;
                }
            }
        }
        System.out.println(moves[b1][b2]);
    }
}

AStart

同样是BFS,但是有一些额外的信息

BFS 是没有目的性的 一圈一圈去搜索, 而 A * 是有方向性的去搜索

启发式函数 要影响的就是队列里元素的排序,去引导搜索方向

队列里节点进行排序,就需要给每一个节点权值

每个节点的权值为F,给出公式为:F = G + H

G:起点达到目前遍历节点的距离

H:目前遍历的节点到达终点的距离

距离计算公式

本题的图是无权网格状,在计算两点距离通常有如下三种计算方式:

  1. 曼哈顿距离,计算方式: d = abs(x1-x2)+abs(y1-y2)
  2. 欧氏距离(欧拉距离) ,计算方式:d = sqrt( (x1-x2)^2 + (y1-y2)^2 )
  3. 切比雪夫距离,计算方式:d = max(abs(x1 - x2), abs(y1 - y2))

本题,采用欧拉距离才能最大程度体现 点与点之间的距离。

所以 使用欧拉距离计算 和 广搜搜出来的最短路的节点数是一样的。 (路径可能不同,但路径上的节点数是相同的)

A * 算法的寻路过程,动画地址:https://kamacoder.com/tools/knight.html

通过优先级队列选择节点

@FunctionalInterface
interface Heuristic {
    int apply(int a1, int a2, int b1, int b2);
}


public class Main {
    public static void main(String[] args) {
        new Main().solve();
    }

    public void solve() {
        Scanner sc = null;
        try {
             sc = new Scanner(new File("1.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        int n = sc.nextInt();
        for (int i=0; i<n; i++) {
            int a1 = sc.nextInt();
            int a2 = sc.nextInt();
            int b1 = sc.nextInt();
            int b2 = sc.nextInt();
            Heuristic myHeuristic = 
                   (x1,y1,x2,y2) -> {return (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2);};
            AStar(a1,a2,b1,b2, myHeuristic);
        }

    }

    public void AStar(int a1, int a2, int b1, int b2, Heuristic heuristic) {

        int[][] dir = {{-2,-1}, {-2,1}, {-1,2}, {1,2}, {2,1}, {2,-1}, {1,-2}, 
        {-1,-2},};

        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(
                (a, b) -> {return Integer.compare(a[2], b[2]);});
        queue.add(new int[]{a1,a2,0});
        int[][] moves = new int[1001][1001];// 1000 * 1000的棋盘

        while (!queue.isEmpty()) {
            int[] pos = queue.poll();
            int x = pos[0];
            int y = pos[1];
            int f = pos[2];
            if (x == b1 && y == b2) break;

            for (int i=0; i<8; i++) {
                int xx = x+dir[i][0];
                int yy = y+dir[i][1];
                if (xx >= 1 && xx <= 1000 && yy >= 1 && yy <= 1000 && moves[xx][yy]==0) {
                    // 这里的g的计算为什么是这样子的啊?
                        // 起点达到目前遍历节点的距离
                    int g1 = heuristic.apply(a1, a2, xx, yy);
                    int g = f + 5;

                    int h = heuristic.apply(xx, yy, b1, b2);
                    int ff = g + h;

                    queue.add(new int[]{xx, yy, ff});
                    moves[xx][yy] = moves[x][y] + 1;
                }
            }

        }
        System.out.println(moves[b1][b2]);
    }

}


http://www.kler.cn/a/457511.html

相关文章:

  • kafka开机自启失败问题处理
  • 我用AI学Android Jetpack Compose之开篇
  • 低代码引擎插件开发:开启开发的便捷与创新之路
  • 快速上手LangChain(三)构建检索增强生成(RAG)应用
  • AE RFG 1251 Generator User Manual
  • oceanbase集群访问异常问题处理
  • Bash语言的并发编程
  • 算法排序算法
  • 【每日学点鸿蒙知识】worker线程数量、判断用户是否进行权限决定、图片上传类型错误、request锁释放时机、H5问题
  • Zynq PS端外设之中断控制器
  • FFmpeg来从HTTP拉取流并实时推流到RTMP服务器
  • 自学记录鸿蒙API 13:实现智能文本识别Core Vision Text Recognition
  • Django中使用 `formfield_for_choice_field` 和 `get_form` 方法自定义管理后台表单
  • 26、使用StreamPark管理Flink作业中,关于flink on k8s部分的提交处理
  • driftingblues6靶机
  • Oracle数据库高级应用与优化策略
  • 2-194基于matlab的四足机器人行走程序设计
  • [ffmpeg]编译 libx264
  • FFmpeg:详细安装教程与环境配置指南
  • 【Rust自学】7.4. use关键字 Pt.1:use的使用与as关键字
  • 基于Python的企业招聘管理系统
  • UniApp 打开文件工具,获取文件类型,判断文件类型
  • QT中使用OpenGL function
  • uDDS源程序subscriber
  • Web漏洞知识梳理笔记--XSS漏洞原理、类型、危害、利用方式、权限维持、防御措施等
  • 【已解决】“Content-Security-Policy”头缺失