Day46 | 101孤岛的总面积 102沉没孤岛 103水流问题 104建造最大岛屿

news2024/11/15 19:27:12

语言

Java

101.孤岛的总面积

101. 孤岛的总面积

题目

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。

现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0。

输出描述

输出一个整数,表示所有孤岛的总面积,如果不存在孤岛,则输出 0。

思路

  1. 使用BFS(广度优先搜索)
    • 遍历网格的边界,对边界上的1(障碍物)进行BFS。
    • 通过BFS将与边界相连的障碍物(即不被完全包围的障碍物)及其可达的所有障碍物都标记为0
  2. 第二次遍历
    • 再次遍历整个网格,此时剩余的1即为完全被包围的障碍物。
    • 对每个剩余的1执行BFS,并计算数量。
  3. 输出
    • 输出被完全包围的障碍物的总数。

代码

import java.util.*;

public class Main {
    private static int count = 0;
    private static final int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四个方向

    private static void bfs(int[][] grid, int x, int y) {
        Queue<int[]> que = new LinkedList<>();
        que.add(new int[]{x, y});
        grid[x][y] = 0; // 只要加入队列,立刻标记
        count++;
        while (!que.isEmpty()) {
            int[] cur = que.poll();
            int curx = cur[0];
            int cury = cur[1];
            for (int i = 0; i < 4; i++) {
                int nextx = curx + dir[i][0];
                int nexty = cury + dir[i][1];
                if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue; // 越界了,直接跳过
                if (grid[nextx][nexty] == 1) {
                    que.add(new int[]{nextx, nexty});
                    count++;
                    grid[nextx][nexty] = 0; // 只要加入队列立刻标记
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[][] grid = new int[n][m];
        
        // 读取网格
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                grid[i][j] = scanner.nextInt();
            }
        }
        
        // 从左侧边,和右侧边向中间遍历
        for (int i = 0; i < n; i++) {
            if (grid[i][0] == 1) bfs(grid, i, 0);
            if (grid[i][m - 1] == 1) bfs(grid, i, m - 1);
        }
        
        // 从上边和下边向中间遍历
        for (int j = 0; j < m; j++) {
            if (grid[0][j] == 1) bfs(grid, 0, j);
            if (grid[n - 1][j] == 1) bfs(grid, n - 1, j);
        }
        
        count = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == 1) bfs(grid, i, j);
            }
        }

        System.out.println(count);
    }
}

易错点

  1. 边界处理:在BFS过程中,必须正确处理边界条件,以避免数组越界错误。
  2. 重复计数:在第二次遍历中,需要确保不对已经被标记为0的障碍物进行重复计数。
  3. 重置计数器:在第二次遍历前,需要重置count计数器,以确保计数的准确性。

102.沉没孤岛

102. 沉没孤岛

题目

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。

现在你需要将所有孤岛“沉没”,即将孤岛中的所有陆地单元格(1)转变为水域单元格(0)。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。

之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出将孤岛“沉没”之后的岛屿矩阵。 注意:每个元素后面都有一个空格

思路

  1. 初始化

    • 读取输入的网格大小 n 和 m
    • 读取网格内容并存储在二维数组 grid 中。
  2. 边界遍历

    • 从网格的四条边(左、右、上、下)开始,向中间进行DFS遍历。
    • 如果当前位置是岛屿(值为1),则调用DFS方法进行标记。
  3. DFS标记

    • 在DFS方法中,将当前位置标记为已访问(值为2)。
    • 向四个方向(上、下、左、右)进行递归遍历,继续标记相邻的岛屿。
  4. 转换结果

    • 遍历整个网格,将未标记的岛屿(值为1)置为0,已标记的岛屿(值为2)置为1。
  5. 输出结果

    • 打印最终的网格。

代码

import java.util.Scanner;

public class Main {
    private static final int[][] DIR = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; // 保存四个方向

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int[][] grid = new int[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                grid[i][j] = scanner.nextInt();
            }
        }

        // 步骤一:
        // 从左侧边,和右侧边 向中间遍历
        for (int i = 0; i < n; i++) {
            if (grid[i][0] == 1) dfs(grid, i, 0);
            if (grid[i][m - 1] == 1) dfs(grid, i, m - 1);
        }

        // 从上边和下边 向中间遍历
        for (int j = 0; j < m; j++) {
            if (grid[0][j] == 1) dfs(grid, 0, j);
            if (grid[n - 1][j] == 1) dfs(grid, n - 1, j);
        }

        // 步骤二、步骤三
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == 1) grid[i][j] = 0;
                if (grid[i][j] == 2) grid[i][j] = 1;
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(grid[i][j] + " ");
            }
            System.out.println();
        }
    }

    private static void dfs(int[][] grid, int x, int y) {
        grid[x][y] = 2;
        for (int i = 0; i < 4; i++) { // 向四个方向遍历
            int nextX = x + DIR[i][0];
            int nextY = y + DIR[i][1];
            // 超过边界
            if (nextX < 0 || nextX >= grid.length || nextY < 0 || nextY >= grid[0].length) continue;
            // 不符合条件,不继续遍历
            if (grid[nextX][nextY] == 0 || grid[nextX][nextY] == 2) continue;
            dfs(grid, nextX, nextY);
        }
    }
}

易错点、

  1. 边界条件

    • 在DFS遍历时,需要检查下一个位置是否越界。如果越界,则跳过该方向。
    • 在遍历过程中,需要检查当前位置是否已经是已访问状态(值为2)或不是岛屿(值为0),如果是,则跳过该位置。
  2. 输入读取

    • 确保正确读取输入的网格大小和内容,避免数组越界或读取错误。

103.水流问题

103. 水流问题

题目

题目描述

现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界,而矩阵的右边界和下边界被视为第二组边界。

矩阵模拟了一个地形,当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。

输入描述

第一行包含两个整数 N 和 M,分别表示矩阵的行数和列数。 

后续 N 行,每行包含 M 个整数,表示矩阵中的每个单元格的高度。

输出描述

输出共有多行,每行输出两个整数,用一个空格隔开,表示可达第一组边界和第二组边界的单元格的坐标,输出顺序任意。

思路

  1. 初始化

    • 读取输入的矩阵大小 N 和 M
    • 读取矩阵内容并存储在二维数组 matrix 中。
  2. 边界标记

    • 使用一个布尔数组 visited 来标记已经访问过的单元格。
    • 使用两个队列 queue1 和 queue2 分别存储可以流向第一组边界和第二组边界的单元格。
  3. 初始入队

    • 将第一组边界和第二组边界的单元格分别加入对应的队列,并标记为已访问。
  4. BFS遍历

    • 从队列中取出单元格,向四个方向(上、下、左、右)进行遍历。
    • 如果相邻单元格的高度大于等于当前单元格且未访问过,则将其加入队列并标记为已访问。
  5. 输出结果

    • 遍历整个矩阵,输出所有已访问的单元格的坐标。

代码

import java.util.*;


public class Main {

    // 采用 DFS 进行搜索
    public static void dfs(int[][] heights, int x, int y, boolean[][] visited, int preH) {
        // 遇到边界或者访问过的点,直接返回
        if (x < 0 || x >= heights.length || y < 0 || y >= heights[0].length || visited[x][y]) return;
        // 不满足水流入条件的直接返回
        if (heights[x][y] < preH) return;
        // 满足条件,设置为true,表示可以从边界到达此位置
        visited[x][y] = true;

        // 向下一层继续搜索
        dfs(heights, x + 1, y, visited, heights[x][y]);
        dfs(heights, x - 1, y, visited, heights[x][y]);
        dfs(heights, x, y + 1, visited, heights[x][y]);
        dfs(heights, x, y - 1, visited, heights[x][y]);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();

        int[][] heights = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                heights[i][j] = sc.nextInt();
            }
        }

        // 初始化两个二位boolean数组,代表两个边界
        boolean[][] pacific = new boolean[m][n];
        boolean[][] atlantic = new boolean[m][n];

        // 从左右边界出发进行DFS
        for (int i = 0; i < m; i++) {
            dfs(heights, i, 0, pacific, Integer.MIN_VALUE);
            dfs(heights, i, n - 1, atlantic, Integer.MIN_VALUE);
        }

        // 从上下边界出发进行DFS
        for (int j = 0; j < n; j++) {
            dfs(heights, 0, j, pacific, Integer.MIN_VALUE);
            dfs(heights, m - 1, j, atlantic, Integer.MIN_VALUE);
        }

        // 当两个边界二维数组在某个位置都为true时,符合题目要求
        List<List<Integer>> res = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (pacific[i][j] && atlantic[i][j]) {
                    res.add(Arrays.asList(i, j));
                }
            }
        }

        // 打印结果
        for (List<Integer> list : res) {
            for (int k = 0; k < list.size(); k++) {
                if (k == 0) {
                    System.out.print(list.get(k) + " ");
                } else {
                    System.out.print(list.get(k));
                }
            }
            System.out.println();
        }
    }
}

易错点

  1. 边界条件

    • 在BFS遍历时,需要检查下一个位置是否越界。如果越界,则跳过该方向。
    • 在遍历过程中,需要检查当前位置是否已经访问过,如果是,则跳过该位置。
  2. 输入读取

    • 确保正确读取输入的矩阵大小和内容,避免数组越界或读取错误。
  3. BFS队列

    • 在BFS遍历时,确保正确地将相邻单元格加入队列,并标记为已访问。

104.建造最大岛屿

104. 建造最大岛屿

题目

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。

岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示最大的岛屿面积。

思路

  1. 初始化

    • 读取输入的矩阵大小 m 和 n
    • 读取矩阵内容并存储在二维数组 grid 中。
  2. DFS遍历

    • 使用DFS遍历矩阵,将每个岛屿标记为不同的数字,并记录每个岛屿的面积。
    • 使用一个布尔数组 visited 来标记已经访问过的单元格。
    • 使用一个 HashMap 来记录每个岛屿的标记号和面积。
  3. 计算最大面积

    • 再次遍历矩阵,对于每个水域单元格,检查其四周的岛屿,并计算这些岛屿的面积之和。
    • 使用一个 HashSet 来记录当前水域单元格四周的不同岛屿标记号,避免重复计算。
    • 更新最大面积 result
  4. 输出结果

    • 打印最终的最大面积 result

代码

import java.util.*;

public class Main {
    // 该方法采用 DFS
    // 定义全局变量
    // 记录每次每个岛屿的面积
    static int count;
    // 对每个岛屿进行标记
    static int mark;
    // 定义二维数组表示四个方位
    static int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

    // DFS 进行搜索,将每个岛屿标记为不同的数字
    public static void dfs(int[][] grid, int x, int y, boolean[][] visited) {
        // 当遇到边界,直接return
        if (x < 0 || x >= grid.length || y < 0 || y >= grid[0].length) return;
        // 遇到已经访问过的或者遇到海水,直接返回
        if (visited[x][y] || grid[x][y] == 0) return;

        visited[x][y] = true;
        count++;
        grid[x][y] = mark;

        // 继续向下层搜索
        dfs(grid, x, y + 1, visited);
        dfs(grid, x, y - 1, visited);
        dfs(grid, x + 1, y, visited);
        dfs(grid, x - 1, y, visited);
    }

    public static void main (String[] args) {
        // 接收输入
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();

        int[][] grid = new int[m][n];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                grid[i][j] = sc.nextInt();
            }
        }

        // 初始化mark变量,从2开始(区别于0水,1岛屿)
        mark = 2;

        // 定义二位boolean数组记录该位置是否被访问
        boolean[][] visited = new boolean[m][n];

        // 定义一个HashMap,记录某片岛屿的标记号和面积
        HashMap<Integer, Integer> getSize = new HashMap<>();

        // 定义一个HashSet,用来判断某一位置水四周是否存在不同标记编号的岛屿
        HashSet<Integer> set = new HashSet<>();

        // 定义一个boolean变量,看看DFS之后,是否全是岛屿
        boolean isAllIsland = true;

        // 遍历二维数组进行DFS搜索,标记每片岛屿的编号,记录对应的面积
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 0) isAllIsland = false;
                if (grid[i][j] == 1) {
                    count = 0;
                    dfs(grid, i, j, visited);
                    getSize.put(mark, count);
                    mark++;
                }
            }
        }

        int result = 0;
        if (isAllIsland) result =  m * n;

        // 对标记完的grid继续遍历,判断每个水位置四周是否有岛屿,并记录下四周不同相邻岛屿面积之和
        // 每次计算完一个水位置周围可能存在的岛屿面积之和,更新下result变量
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 0) {
                    set.clear();
                    // 当前水位置变更为岛屿,所以初始化为1
                    int curSize = 1;

                    for (int[] dir : dirs) {
                        int curRow = i + dir[0];
                        int curCol = j + dir[1];

                        if (curRow < 0 || curRow >= m || curCol < 0 || curCol >= n) continue;
                        int curMark = grid[curRow][curCol];
                        // 如果当前相邻的岛屿已经遍历过或者HashMap中不存在这个编号,继续搜索
                        if (set.contains(curMark) || !getSize.containsKey(curMark)) continue;
                        set.add(curMark);
                        curSize += getSize.get(curMark);
                    }

                    result = Math.max(result, curSize);
                }
            }
        }

        // 打印结果
        System.out.println(result);
    }
}

易错点

  1. 边界条件

    • 在DFS遍历时,需要检查下一个位置是否越界。如果越界,则跳过该方向。
    • 在遍历过程中,需要检查当前位置是否已经访问过,如果是,则跳过该位置。
  2. 输入读取

    • 确保正确读取输入的矩阵大小和内容,避免数组越界或读取错误。
  3. DFS递归

    • 在DFS递归调用时,确保传递正确的坐标参数,避免递归调用错误。

总结

这几道题是又考验思路又有难度。

继续加油,早日解决岛屿问题。

有必胜信念的人才能成为战场上的胜利者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2067079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

植物大战僵尸杂交版v2.3.7最新版本(附下载链接)

新版本更新啦&#xff01; B站游戏作者潜艇伟伟迷于8月19日更新了植物大战僵尸杂交版2.3.7版本&#xff01;&#xff01;&#xff01; v2.3.7版本更新内容&#xff1a; 游戏分辨率扩充&#xff0c;UI界面翻新&#xff0c;卡槽数量提升至16个&#xff0c;修复大量BUG&#xff0c…

网络协议与IO模型

1、说一说网络模型&#xff08;OSI、TCP/IP模型&#xff09; OSI采用了分层的结构化技术&#xff0c;共分七层&#xff0c; 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层 。 Open System Interconnect 简称OSI&#xff0c;是国际标准化组织(ISO)和国际电报电…

【Windows脚本】如何测试远程主机某个端口是否开放?

概要 如何测试远程主机某个端口是否开放&#xff1f; 1、PowerShell脚本 使用Test-NetConnection 指令&#xff0c;命令如下。 Test-NetConnection RemoteIP -Port 80 -InformationLevel Detailed 2、tcping工具 下载地址&#xff1a;https://download.csdn.net/download/…

工具(1)查看YUV 图

#灵感# 没啥灵感&#xff0c;就是脑子越来越健忘&#xff0c;就啥都记一笔。 工具名字&#xff1a;YUVPlayer 操作流程&#xff1a; 1、打开YUVPlayer, 把YUV文件拖进来。 2、如果拖进来失败&#xff0c;需要先设置属性, 尤其是YUV类型。 3、成功打开图片后&#xff0c;如…

Linux批量验证代理IP的实用方法

在网络管理和优化过程中&#xff0c;批量验证代理IP的有效性是一个常见需求。无论是为了提高网络访问速度&#xff0c;还是为了确保代理IP的可用性&#xff0c;批量验证代理IP都是一项重要的任务。本文将详细介绍如何在Linux环境下批量验证代理IP&#xff0c;帮助你高效地管理和…

短剧小程序源码2023 短剧影视付费查看小视频会员收益系统全开源

本文来自&#xff1a;短剧小程序源码2023 短剧影视付费查看小视频会员收益系统全开源 - 源码1688 应用介绍 演示后台&#xff1a;http://duan.hengchuang.top/VwmRIfEYDH.php 后台账号&#xff1a;admin 后台密码&#xff1a;123456 功能介绍&#xff1a; 1&#xff0c;内容…

《白蛇:浮生》后劲不足,国漫败走2024暑期档

截止到8月19日中午&#xff0c;上映10天的动画电影《白蛇&#xff1a;浮生》票房终于突破3亿。 客观来说&#xff0c;3亿票房在今年暑期档不算差&#xff0c;但对于上映首日就拿到1.29亿票房的《白蛇&#xff1a;浮生》而言&#xff0c;后期票房走势确实没有达到预期&#xff…

4 nesjs IOC控制反转 DI依赖注入

在 NestJS 中&#xff0c;IOC&#xff08;控制反转&#xff09;和 DI&#xff08;依赖注入&#xff09;是核心概念&#xff0c;它们使得应用程序的模块化和解耦变得更加容易。 控制反转&#xff08;IOC&#xff0c;Inversion of Control&#xff09; 控制反转是一个设计原则&…

clickhouse中使用ReplicatedMergeTree表引擎数据去重问题

问题&#xff1a;使用ReplicatedMergeTree表引擎&#xff0c;该引擎逻辑上是不会对于主键相同的数据&#xff0c;进行去重合并操作。如果想要去重&#xff0c;可以使用ReplacingReplicatedMergeTree表引擎。然后使用ReplicatedMergeTree表引擎进行数据insert 插入数据&#xff…

数据防泄密之源代码防泄密的七大要则!

在数字化时代&#xff0c;源代码的安全保护对企业至关重要。它是企业创新和竞争力的核心&#xff0c;一旦泄露&#xff0c;可能会带来不可估量的损失。因此&#xff0c;选择一款合适的源代码加密软件成为了企业信息安全的关键。SDC沙盒防泄密软件以其独特的技术优势和全面的功能…

Windows 11 时间显示 到秒

效果 第一步 win R --> regedit 打开注册表 第二步 打开该路径HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced 第三步 然后新建一个DWORD&#xff08;32位&#xff09;值。 第四步 文件命名为ShowSecondsInSystemClock&#xff0c;双…

Flask+LayUI开发手记(二):LayUI弹出层表单的校验

LayUI里面layer.open()弹出层是一个十分常用也十分强大的功能&#xff0c;比如我们经常是先把记录以数据表单datatable方式显示出来&#xff0c;然后增删改查的功能就利用layer.open调取另一个form表单页面来进行数据编辑并提交数据完成数据表的更新操作。 同样&#xff0c;Lay…

【Dash】feffery_antd_components 简单入门示例

一、简单了解 feffery_antd_components 简称 fac &#xff0c;是一个基于 Ant Design 的 Dash 第三方组件&#xff0c;由Feffery 老师开源维护的 Python 网页开发组件库&#xff0c;它具有丰富的页面常用交互组件功能&#xff0c;使开发者可以使用纯Python的方式快速构建现代…

【工作记录】springboot中基于redis实现地理位置相关需求@20240822

背景 近期收到一个需求&#xff0c;有个事件管理系统&#xff0c;存储了用户上报上来的事件信息&#xff0c;其中包含了事件发生的经纬度&#xff0c;还有另外一个系统中保存了一系列的摄像头数据&#xff0c;也包含经纬度信息。 需求是这样的&#xff0c;用户点击某个事件的…

OpenSBI的PMP

概述 在RISC-V体系架构中&#xff0c;PMP是用于保护物理内存访问权限的机制。PMP机制允许为不同的物理内存区域指定访问权限&#xff08;读、写、执行&#xff09;。这种机制使得运行在RISC-V处理器上的软件只能访问被明确授权的物理地址空间&#xff0c;从而提高了系统的安全…

5.登录功能的开发

登录功能的开发 一、前端1.1首页跳转到登录页面1.2登录界面处理 二、后端2.1创建User实体类2.2创建UserDto类2.3创建UserServlet类 三、效果演示四、轻提示组件 一、前端 1.1首页跳转到登录页面 登录页面是一个单独的页面&#xff0c;我们需要从项目的首页跳转到登录页面。具…

OpenAI Whisper Cannot Import Numpy

题意&#xff1a;“OpenAI Whisper 无法导入 Numpy” 问题背景&#xff1a; I am trying to run the OpenAI Whisper model but running into the following error when trying to run my script: “我正在尝试运行 OpenAI Whisper 模型&#xff0c;但在运行脚本时遇到了以下…

【全网行为管理解决方案】上网行为系统有哪些?

全网行为管理系统是一种用于监控、管理和优化企业内部网络中所有用户活动及网络流量的技术解决方案。 这类系统可以帮助企业提高网络安全、优化网络性能&#xff0c;并确保网络使用符合公司政策及法规要求。以下是几种常用的上网行为管理系统&#xff1a; 一、安企神 特点&am…

防范小程序隐私合规风险,筑牢用户信任防线

随着国内APP软件生态的成熟&#xff0c;依托于头部APP的小程序逐渐成为零售、娱乐、出行等行业必选的获客渠道之一。较低的开发成本和成熟的用户营销功能&#xff0c;令小程序的数量在过去几年呈指数级增长。截止2023年&#xff0c;头部APP内集成的小程序总量已超千万。然而&am…

【业余玩儿AI】【文档问答】实操记录0822

电梯 前文回顾继续踩坑实录从头来过,docker部署Ollama我一定是被偷听了,大数据之神把我拉出泥潭时间回到白天,模型初窥时间回到开心的链接上Ollama那一刻 按捺住乱撞的小鹿,我去准备下文的剧情了 前文回顾 这里书接上文,上文说到: 目标是文档问答,先是本地部署了Marker,然后又…