Leetcode-BFS问题

news2025/5/13 14:11:27

LeetCode-BFS问题

1.Floodfill问题
1.图像渲染问题 [https://leetcode.cn/problems/flood-fill/description/](https://leetcode.cn/problems/flood-fill/description/)
class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        //可以借助另一个数组来完成
        int rows=image.length;
        int cols=image[0].length;
        //默认为一个false
        boolean nums2[][]=new boolean[rows][cols];
        int ret=image[sr][sc];
        image[sr][sc]=color;
        nums2[sr][sc]=true;

        int[] position=new int[]{sr,sc};
        Queue<int [] > queue=new LinkedList<>();
        queue.offer(position);
        while(!queue.isEmpty()) {
            int size=queue.size();
            while(size>0) {
                int [] nums1=queue.poll();
                int row=nums1[0];
                int col=nums1[1];
                if(row-1>=0 && image[row-1][col] ==ret && nums2[row-1][col]==false) {
                    queue.offer(new int[]{row-1,col});
                    nums2[row-1][col]=true;
                }
                 if(col-1>=0 && image[row][col-1] ==ret && nums2[row][col-1]==false) {
                    queue.offer(new int[]{row,col-1});
                    nums2[row][col-1]=true;
                }
                 if(col+1<=cols-1 && image[row][col+1] ==ret && nums2[row][col+1]==false) {
                    queue.offer(new int[]{row,col+1});
                    nums2[row][col+1]=true;
                }
                 if(row+1<=rows-1 && image[row+1][col] ==ret && nums2[row+1][col]==false) {
                    queue.offer(new int[]{row+1,col});
                    nums2[row+1][col]=true;
                }
                image[row][col]=color;
                size--;
            }
        }
        return image;
    }
}

从一个位置开始将上下左右的连接起来的渲染成color。当我们拿到这道题的时候,可能想不到bfs也就是层序遍历。如果我仔细相想一下如果从一个点开始向周围蔓延,这有可能会想到层序遍历。

从(1,1)这个位置开始,这个位置值设为target,开始向上下左右四个方向遍历,如果值跟target相同就加入队列。但是问题也就来了 ,如果当我们遍历到左边时候,按照以上的说法仍会将右边的值加入到队列中。如下图所示

所以这个时候就初始化一个跟原有的数组一样大,来记录那些地方我们已经走过了,也就是代码上面的nums2数组,当我们加入到队列的时候,设置为true。队列中为一个二元组,是这个元素的横坐标和纵坐标。

2.岛屿数量 https://leetcode.cn/problems/number-of-islands/

class Solution {
    public int numIslands(char[][] grid) {
        char ret='1';//代表的是岛屿的标志
        boolean [][] nums2=new boolean[300][300];
        int ans=0;
        Queue<int [] >queue=new LinkedList<>();

        int rows=grid.length;
        int cols=grid[0].length;
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                if(grid[i][j] == ret && nums2[i][j]==false) {
                    queue.offer(new int []{i,j});
                    nums2[i][j]=true;
                    while(!queue.isEmpty()) {
                        int size=queue.size();
                        while(size>0) {
                            int [] nums1=queue.poll();
                            int row=nums1[0];
                            int col=nums1[1];
                            if(row-1>=0 && grid[row-1][col] ==ret && nums2[row-1][col]==false) {
                                queue.offer(new int[]{row-1,col});
                                nums2[row-1][col]=true;
                            }
                            if(col-1>=0 && grid[row][col-1] ==ret && nums2[row][col-1]==false) {
                                queue.offer(new int[]{row,col-1});
                                nums2[row][col-1]=true;
                            }
                            if(col+1<=cols-1 && grid[row][col+1] ==ret && nums2[row][col+1]==false) {
                                queue.offer(new int[]{row,col+1});
                                nums2[row][col+1]=true;
                            }
                            if(row+1<=rows-1 && grid[row+1][col] ==ret && nums2[row+1][col]==false) {
                                queue.offer(new int[]{row+1,col});
                                nums2[row+1][col]=true;
                            }
                            size--;
                        }
                    }
                    ans++;
                }
            }
        }
        return ans;
    }
}

这道题是求连起来的岛屿的数量,也就是层序遍历了几次,统计层序遍历的结果。

这一段代码有一些冗余以及不美观,下面的题目会使用两个数组的形式来控制这个上下左右方向的走向。

3.岛屿的最大面积 https://leetcode.cn/problems/max-area-of-island/description/

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        //感觉还是一样的魔板
        int rows=grid.length;
        int cols=grid[0].length;
        int ret=1;
        //用来记录岛屿的面积
        int ans=0;
        Queue<int [] >queue=new LinkedList<>();
        boolean [][] nums2=new boolean [50][50];
        for(int i=0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                if(grid[i][j]==ret && nums2[i][j]==false) {
                    queue.offer(new int[]{i,j});
                    nums2[i][j]=true;
                    int count=0;
                    while(!queue.isEmpty()) {
                        int size=queue.size();
                        count+=size;
                        while(size>0) {
                            int [] nums1=queue.poll();
                            int row=nums1[0];
                            int col=nums1[1];
                            if(row-1>=0 && grid[row-1][col] ==ret && nums2[row-1][col]==false) {
                                queue.offer(new int[]{row-1,col});
                                nums2[row-1][col]=true;
                                
                            }
                            if(col-1>=0 && grid[row][col-1] ==ret && nums2[row][col-1]==false) {
                                queue.offer(new int[]{row,col-1});
                                nums2[row][col-1]=true;
                                
                            }
                            if(col+1<=cols-1 && grid[row][col+1] ==ret && nums2[row][col+1]==false) {
                                queue.offer(new int[]{row,col+1});
                                nums2[row][col+1]=true;
                                
                            }
                            if(row+1<=rows-1 && grid[row+1][col] ==ret && nums2[row+1][col]==false) {
                                queue.offer(new int[]{row+1,col});
                                nums2[row+1][col]=true;
                            }
                            size--;
                        }
                    }
                     ans=Math.max(ans,count);
                }
            }
        }
        return ans;
    }
}

统计出岛屿的最大面积,就是在统计出岛屿的时候,再计算一步岛屿的面积,由于一个格子的面积是1。当我们进入到层序遍历的时候,使用count变量依次加上队列中这一层的格子数,注意一个岛屿一般都是有很多层的。进入到下一个岛屿遍历的时候,重新初始化count变量。

4.被围绕的区域 https://leetcode.cn/problems/surrounded-regions/description/

class Solution {
      int [] dx={1,-1,0,0};
        int [] dy={0,0,1,-1};
    public void solve(char[][] grid) {
        //感觉还是一样的魔板
        //先遍历周围的模块

        char tmp='A';
        int rows=grid.length;
        if(rows==0) {
            return;
        }
        int cols=grid[0].length;
        Queue<int [] > queue=new LinkedList<>();

        for(int i =0;i<cols;i++) {
            if(grid[0][i]=='O') {
                queue.offer(new int[] {0,i});
                grid[0][i]=tmp; 
            }
            if(grid[rows-1][i]=='O') {
                queue.offer(new int[]{rows-1,i});
                grid[rows-1][i]=tmp;
            }
        }    
        for(int i=1;i<rows-1;i++) {
            if(grid[i][0]=='O') {
                queue.offer(new int []{i,0});
                grid[i][0]=tmp;
               
            }
            if(grid[i][cols-1]=='O') {
                queue.offer(new int[] {i,cols-1});
                grid[i][cols-1]=tmp;
            }
        }
            while(!queue.isEmpty()) {
                    int [] nums1= queue.poll();
                    int row=nums1[0];
                    int col=nums1[1];
                    for(int k=0;k<4;k++) {
                        int a=row+dx[k],b=col+dy[k];
                        if(a>=0 && a<rows && b>=0 && b<cols && grid[a][b]=='O' ) {
                            queue.offer(new int []{a,b});
                            grid[a][b]=tmp;
                        }
                    }
                }
        for(int i =0;i<rows;i++) {
            for(int j =0;j<cols;j++) {
                if(grid[i][j]==tmp) {
                    grid[i][j]='O';
                }else if(grid[i][j]=='O') {
                    grid[i][j]='X';
                }
            }
        }
    }
}

当我们还是按照上面题目的思想来解决这道题目的话,是行不通的。我们仔细观察题目只要区域中包含有外围的格子他就不是被包围的区域,于是我们先遍历周围的格子将周围相连的格子变成tmp,经过bfs之后再进行遍历数组,将tmp的变成’0’,将’0’变成’X’,正难则反,先将不被包围的区域变成一个tmp,再将被包围的区域变成一个’X’。

2.解决最短路问题
1.迷宫中离入口最近的出口 [https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/description/](https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/description/)
class Solution {
    public int nearestExit(char[][] nums, int[] entrance) {
        // +表示墙,.表示的是一个可走的路
        int rows=nums.length;
        int cols=nums[0].length;

        int [] dx=new int[] {0,0,1,-1};
        int [] dy=new int[] {1,-1,0,0};

        boolean [][] visit=new boolean[rows][cols];

        int a=entrance[0],b=entrance[1];

        Queue<int[] > queue=new LinkedList<>();
        queue.offer(new int[]{a,b});
        visit[a][b]=true;

        int ans=0;
        while(!queue.isEmpty()) {
            ans++;
            int size=queue.size();
            for(int i =0;i<size;i++) {
                int [] tmp=queue.poll();
                int row=tmp[0],col=tmp[1];

                for(int j=0;j<4;j++) {
                    int x=row+dx[j],y=col+dy[j];
                    if(x>=0 && y>=0 && x<rows && y<cols && !visit[x][y] && nums[x][y]=='.') {
                        if(x==0 || x==rows-1 || y==0 || y==cols-1) {
                            return ans;
                        }
                        queue.offer(new int[] {x,y});
                        visit[x][y]=true;
                    }
                }
                
            }
        }
        return -1;
    }
}

这里研究的最短路的问题边权都是为1的最短路问题。这里为什么能用bfs来解决,如下图说明。

以红点出发有四个方向可以走,上下左右四个方向。当然这里我们并没有实际走,只是在逻辑上走。

其实这个过程是将所有的结果给枚举出来,结果就是进行几次层序遍历。当我们碰到一个节点为’.'的时候,此时位置正好为边缘的时候,我们将结果返回。为什么进行几层层序遍历就是最小值呢,是因为我们在一层一层进行遍历,遍历的同时看是否到达出口,如果提前有出口,我们也就提前返回了。

2.最小基因变化 https://leetcode.cn/problems/minimum-genetic-mutation/description/

class Solution {
    public int minMutation(String start, String end, String[] bank) {
        if(bank.length==0 || bank==null) {
            return -1;
        } 
        if(start==end) {
            return 0;
        }
        // 也就是说当我们在进行变化的时候,只有当是基因库中的才有效
        Queue<String> queue=new LinkedList<>();
        //这里使用哈希表来进行记录已经遍历过的
        Map<String,Boolean> hash=new HashMap<>();
        for(String str:bank) {
            hash.put(str,false);
        }
        int ans=0;
        char[] nums={'A','C','G','T'};
        queue.offer(start);

        while(!queue.isEmpty()) {
            int size=queue.size();
            ans++;
            while(size>0) {
                String tmp=queue.poll();
                for(int i=0;i<tmp.length();i++) {
                    // 每个字符就会对应出4个结果
                    for(int j =0;j<4;j++) {
                        // 这里无法在原有的字符串上面进行更改值
                        String ret= tmp.substring(0,i)+nums[j]+tmp.substring(i+1,8);
                        if(ret.equals(end) && hash.containsKey(ret)) {
                            return ans;
                        }
                        if(hash.containsKey(ret) && hash.get(ret)==false) {
                            queue.offer(ret);
                            hash.put(ret,true);
                        }
                    }
                }
                size--;
            }
        }
        return -1;
    }
}

首先,先创建出一个哈希表用来标志这个基因是否到达过。每个基因的就是一个字符串都是等长的,在每个位置进行变换,于是就有了String ret= tmp.substring(0,i)+nums[j]+tmp.substring(i+1,8);这一行代码。剩下的就是跟之前是一样的,这里的变化必须是基因库的。

3.单词接龙 https://leetcode.cn/problems/om3reC/description/

class Solution {
    public int ladderLength(String start, String end, List<String> word) {
        Map<String,Boolean> hash=new HashMap<>();
        int len=start.length();
        int ans=1;
        for(String str : word) {
            hash.put(str,false);
        }
        Queue<String> queue=new LinkedList<>();
        queue.offer(start);
        while(!queue.isEmpty()) {
            ans++;
            int size=queue.size();
            while(size>0) {
                String tmp=queue.poll();
                for(int i=0;i<len;i++) {
                    for(int j=0;j<26;j++) {
                        char ch=(char)('a'+j);
                        String ret=tmp.substring(0,i)+ch+tmp.substring(i+1,len);
                        if(ret.equals(end) && hash.containsKey(ret)) {
                            return ans;
                        }
                        if(hash.containsKey(ret) && hash.get(ret)==false) {
                            queue.offer(ret);
                            hash.put(ret,true);
                        }
                    }
                }
                size--;
            }
        }
        return 0;
    }
}

这道题跟上面的题是一样,只不过换了一个问法。这里是所以可以使用最短路径解决这道题是因为一个单词可以变换成很多的结果,同时结果单词又能变化成很多单词。

4.为高尔夫比赛砍树 https://leetcode.cn/problems/cut-off-trees-for-golf-event/description/

class Solution {
    int []dx={-1,1,0,0};
    int []dy={0,0,-1,1};
    int ans=0;
    public int cutOffTree(List<List<Integer>> forest) {
        if(forest.get(0).get(0)==0) {
            return -1;
        }
        List<int[]> list=new ArrayList<>();
        int rows=forest.size();
        int cols=forest.get(0).size();
        for(int i =0;i<rows;i++) {
            for(int j=0;j<cols;j++) {
                if(forest.get(i).get(j)>1) {
                    list.add(new int[]{i,j});
                }
            }
        }
        //对这个数组进行排序
        Collections.sort(list, (a, b) -> forest.get(a[0]).get(a[1]) - forest.get(b[0]).get(b[1]));
        
        int row=0;
        int col=0;
        for(int i=0;i<list.size();i++) {
            //其实在判断的时候只是要一个位置而已
            //row和col是刚开始位置,肯定要按照顺序找
            int temp=bfs(forest,row,col,list.get(i)[0],list.get(i)[1]);
            if(temp==-1) {
                return -1;
            }
            ans+=temp;
            row=list.get(i)[0];
            col=list.get(i)[1];
        }
        return ans;       
    }
    public int bfs(List<List<Integer>> forest,int row,int col,int targetx,int targety) {
        if(row==targetx && col==targety) {
            return 0;
        }
        //接下里就是宽度搜索
        //其实找到最小的位置,但是注意不能通行的地方
        Queue<int[]> queue=new LinkedList<>();
        int rows=forest.size();
        int cols=forest.get(0).size();
        boolean [][]nums=new boolean[rows][cols];
        int ret=0;
        queue.offer(new int []{row,col});
        nums[row][col]=true;

        while(!queue.isEmpty()) {
            int size=queue.size();
            ret++;
            while(size>0) {
                int[] temp=queue.poll();
                for(int i=0;i<4;i++) {
                    int a=dx[i]+temp[0];
                    int b=dy[i]+temp[1];
                    if(a>=0 && a<rows && b>=0 && b<cols) {
                        if(forest.get(a).get(b)>0 && !nums[a][b]) {
                            if(a==targetx && b==targety) {
                                return ret;
                            }
                            queue.offer(new int[]{a,b});
                            nums[a][b]=true;
                        }
                    }
                }
                size--;
            }
        }
        return -1;
    }
}

首先我们看到题目是要求是从低到高开始砍树,先将所有大于的1位置以二元组的形式,可以使用pair,也可以使用数组的形式加入到数组中。然后对数组进行排序,先从(0,0)位置开始向最小的那个位置开始层序遍历,如果途中我们返回了-1的时候,说明四周遇到了障碍。 boolean [][]nums=new boolean[rows][cols];这个每次调用bfs函数的时候,就创建一次。如下图

当从9到10的时候,同时还会遍历8,1,3,4,6,7这些数字,如果我们将这些数字设置为不能再走了 ,此时返回的结果与预期的结果不同。所以每次进行bfs的时候都重新创建一个nums数组。

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

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

相关文章

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】8.4 数据故事化呈现(报告结构设计/业务价值提炼)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 8.4 数据故事化呈现&#xff1a;从报告结构到业务价值的深度融合一、数据故事化的核心价值体系&#xff08;一&#xff09;报告结构设计的黄金框架1. 业务场景锚定&#xff…

专题二:二叉树的深度搜索(二叉树剪枝)

以leetcode814题为例 题目分析&#xff1a; 也就是当你的子树全为0的时候就可以剪掉 算法原理分析&#xff1a; 首先分析问题&#xff0c;你子树全为0的时候才可以干掉&#xff0c;我们可以设递归到某一层的时候如何处理 然后抽象出三个核心问题 也就是假设我们递归到第2层…

Hugging Face推出了一款免费AI代理工具,它能像人类一样使用电脑

Hugging Face推出了一款免费AI代理工具&#xff0c;它能像人类一样使用电脑。 这款工具名为Open Computer Agent&#xff08;开放计算机代理&#xff09;&#xff0c;可模拟真实的电脑操作。 无需安装&#xff0c;在浏览器中即可运行。 以下是一些信息&#xff1a; - Open C…

生成对抗网络(GAN)深度解析:理论、技术与应用全景

生成对抗网络&#xff08;Generative Adversarial Networks,GAN&#xff09;作为深度学习领域的重要突破&#xff0c;通过对抗训练框架实现了强大的生成能力。本文从理论起源、数学建模、网络架构、工程实现到行业应用&#xff0c;系统拆解GAN的核心机制&#xff0c;涵盖基础理…

Python集成开发环境之Thonny

前言&#xff1a;今天介绍一款Python的傻瓜IDE&#xff08;集成开发环境&#xff09;——Thonny&#xff0c;比较适合初学者进行Python程序的开发和学习&#xff0c;为用户提供了代码编辑、调试、运行等一系列功能。 我应该不止两次提到过这个词了“IDE”(集成开发环境)&#…

【超详细教程】安卓模拟器如何添加本地文件?音乐/照片/视频一键导入!

作为一名安卓开发者或手游爱好者&#xff0c;安卓模拟器是我们日常工作和娱乐的重要工具。但很多新手在使用过程中常常遇到一个共同问题&#xff1a;**如何将电脑本地的音乐、照片、视频等文件导入到安卓模拟器中&#xff1f;**今天&#xff0c;我将为大家带来一份全网最详细的…

构建DEEPPOLAR ——Architecture for DEEPPOLAR (256,37)

目录 编码器 解码器 编码器 编码器是大小为的内核的集合ℓ 16,每个都由神经网络g建模。编码器内核g负责编码ℓ 输入。g的架构如下&#xff1a; 表1 DEEPOLAR模型训练中使用的超参数&#xff08;256,37&#xff0c;ℓ16&#xff09; Table 1. Hyperparameters used in model…

使用 DMM 测试 TDR

TDR&#xff08;时域反射计&#xff09;可能是实验室中上升时间最快的仪器&#xff0c;但您可以使用直流欧姆表测试其准确性。 TDR 测量什么 在所有高速通道中&#xff0c;反射都很糟糕。我们尝试设计一个通道来减少反射&#xff0c;这些反射都会导致符号间干扰 &#xff08;…

客户端限流主要采用手段:纯前端验证码、禁用按钮、调用限制和假排队

一、纯前端验证码 场景 防止机器人或脚本高频提交&#xff0c;需用户完成验证后才能触发请求。 Vue 前端实现 <template><div><button click"showCaptcha">提交订单</button><div v-if"captchaVisible"><img :src"…

企业数字化中台建设方案(AI/技术中台、数据中台、业务中台)

构建企业数字化中台需要实现业务、数据、AI和技术四大中台的有机协同&#xff0c;形成闭环能力体系。以下是综合建设方案&#xff08;含技术架构和实施路径&#xff09;&#xff1a; 一、建设背景与目标 1.1 行业痛点 生产设备数据孤岛&#xff0c;实时监控能力不足 传统ERP/…

单因子实验方差分析模型的适应性检验

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著傅珏生译)第3章单因子实验 方差分析第3.4节的python解决方案。本文尽量避免重复书中的理论&#xff0c;着于提供python解决方案&#xff0c;并与原书的运算结果进行对比。您可以从Detail 下载实验设计与分析&…

linux CUDA与CUDNN安装教程

目录 1.CUDA安装 1.1.CUDA作用 1.2.CUDA下载 1.3.CUDA安装 1.4.验证 2.CUDNN安装 2.1.CUDNN作用 2.2.下载 2.3.安装 2.4.验证 1.CUDA安装 1.1.CUDA作用 CUDA 是 NVIDIA 提供的并行计算平台和编程模型&#xff0c;允许开发者直接利用 GPU 的并行计算能力&#xff…

添加购物车-02.代码开发

一.代码开发 购物车属于用户端功能&#xff0c;因此要在user下创建controller代码。 Controller层 package com.sky.controller.user;import com.sky.dto.ShoppingCartDTO; import com.sky.entity.ShoppingCart; import com.sky.result.Result; import com.sky.service.Shopp…

Unity动画系统使用整理 --- Playable

​​Playable API​​ 是一个强大的工具&#xff0c;用于更灵活地控制动画、音频、脚本等时间轴内容的播放和混合。它提供了比传统 Animator 更底层、更可控的方式管理时间轴行为&#xff0c;尤其适合复杂动画逻辑或动态内容组合的场景。 优点&#xff1a; 1.Playables API 支…

Xilinx FPGA PCIe | XDMA IP 核 / 应用 / 测试 / 实践

注&#xff1a;本文为 “Xilinx FPGA 中 PCIe 技术与 XDMA IP 核的应用” 相关文章合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文。 FPGA&#xff08;基于 Xilinx&#xff09;中 PCIe 介绍以及 IP 核 XDMA 的使用 N…

winreg查询Windows注册表的一些基本用法

注册表是Windows操作系统中用于存储配置信息的数据库。它包含了关于系统硬件、已安装的应用程序、用户账户设置以及系统设置的信息。 特别地&#xff0c;当我们需要某些软件的配置配息时&#xff0c;主要在HKEY_CURRENT_USER和HKEY_LOCAL_MACHINE下的SoftWare内进行查询操作。 …

计算机网络|| 路由器和交换机的配置

一、实验目的 1. 了解路由器和交换机的工作模式和使用方法&#xff1b; 2. 熟悉 Cisco 网络设备的基本配置命令&#xff1b; 3. 掌握 Cisco 路由器的基本配置方式及配置命令&#xff1b; 4. 掌握路由器和交换机的基本配置与管理方法。 二、实验环境 1. 运行 Windows 操作…

推理加速新范式:火山引擎高性能分布式 KVCache (EIC)核心技术解读

资料来源&#xff1a;火山引擎-开发者社区 分布式 KVCache 的兴起 背景 在大模型领域&#xff0c;随着模型参数规模的扩大和上下文长度增加&#xff0c;算力消耗显著增长。在 LLM 推理过程中&#xff0c;如何减少算力消耗并提升推理吞吐已经成为关键性优化方向。以多轮对话场…

中央处理器(CPU)(概述、指令周期)

一、概述 主要功能&#xff1a;&#xff08;1&#xff09;程序控制&#xff08;2&#xff09;操作控制&#xff08;3&#xff09;时序控制&#xff08;4&#xff09;数据加工&#xff08;5&#xff09;中断处理 组成&#xff1a;早期冯诺依曼计算机的 CPU 主要由运算器和控制…

MiniCPM-V

一、引言 在多模态大语言模型(MLLMs)快速发展的背景下,现有模型因高参数量(如 72B、175B)和算力需求,仅能部署于云端,难以适配手机、车载终端等内存和算力受限的端侧设备。MiniCPM-V聚焦 “轻量高效” 与 “端侧落地”,通过架构创新、训练优化和部署适配,打造高知识密…