端盘子问题(二分查找+广度优先)

server/2024/10/23 18:59:09/

题目描述

终于中午放学铃声打响了,小明想要尽快地前往食堂打自己最喜欢吃的菜。小明觉得能打到喜欢吃的菜越多越好,他会准备好若干个盘子再出发,带了几个盘子就打几份菜。但是一路上人群拥挤程度不同,如果太过拥挤,小明会拿不稳太多盘子。

经过观察,小明发现食堂的地形可以用一个 n × n 的二维平面表示:

  • 初始位置(1,1)
  • 食堂的位置(n,n)
  • 在除开初始位置和食堂位置外的所有格子上,都有一个最大允许的盘子数量,表示小明在经过该格子时最多能带的盘子数量。如果小明带的盘子数量超过这个限制,会被人群挤掉,前功尽弃。

小明只能在二维平面内行走,并且每次可以花费 1 秒,从当前位置 (i, j) 移动到相邻的 (i+1, j)(i, j+1)(i-1, j)(i, j-1)

你需要帮助小明找到:

  • 在 T 秒内从起点 (1,1) 走到终点 (n,n) 时,最多能带多少个盘子。

如果无论如何也不能在规定时间内到达终点,输出 0


输入描述

第一行包含两个整数 nT,分别表示:

  • n:二维平面的大小为 n × n
  • T:时间限制(秒数)

接下来 n 行,每行包含 n 个整数,描述每个位置的最大允许盘子数量:

  • 如果某位置的值为 -1,表示没有限制(即可以带任意数量的盘子)。
  • 起点 (1,1)终点 (n,n) 的值为 -1
  • 其他格子的值为 >= 0,表示该位置的最大允许盘子数量。

输入约束:

  • 1≤n≤10001≤n≤1000
  • 1≤T≤n21≤Tn2
  • −1≤ai,j≤1,000,000−1≤a**i,j≤1,000,000(仅 (1,1)(n,n) 的值为 -1

输出描述

输出一行,表示小明最多能带的盘子数量
如果无论如何也不能在规定时间内到达终点,输出 0

样例输入

4 6
-1 2 1 1
0 2 2 0
0 0 2 2
1 1 0 -1

样例输出

2

解释

在样例输入中,小明需要在 6 秒内从 (1,1) 走到 (4,4)
经过仔细计算,最多可以携带 2 个盘子,否则某些位置的限制无法满足。

提示

  1. 二分查找+广度优先搜索(BFS)

    是解决这个问题的有效方法:

    • 使用 二分查找 来找到可以带的最大盘子数量。
    • 每次假设一个盘子数量,用 BFS 检查是否能在规定时间内从起点走到终点。
  2. 时间复杂度优化:由于 n 最大可以达到 1000,路径搜索需要高效的算法,所以 BFS 是更合适的选择。

解题:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;public class Main {// 四个方向的移动向量,分别表示:向下,向上,向右,向左static int[] dx = {1, -1, 0, 0};static int[] dy = {0, 0, 1, -1};// 定义全局变量n(表示二维平面的大小)和T(表示时间限制)static int n, T;// 定义二维数组grid,用来存储每个格子允许的最大盘子数量static int[][] grid;public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取n和Tn = sc.nextInt();T = sc.nextInt();grid = new int[n][n];// 读取地图数据,即每个格子允许的最大盘子数量for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {grid[i][j] = sc.nextInt();}}// 进行二分查找,查找能带的最大盘子数量int left = 0;       // 二分查找的左边界,最小值是0int right = 1000000; // 二分查找的右边界,最大值为1000000(题目允许的最大值)int result = 0;     // 用来记录最终能带的最大盘子数量// 开始二分查找while (left <= right) {// 取当前的中间值mid,表示我们假设小明能带mid个盘子int mid = (left + right) / 2;// 调用canReach函数判断:带mid个盘子能否在规定的时间T内到达终点if (canReach(mid)) {// 如果可以到达,说明mid是一个可行的解,记录结果并尝试更大的值result = mid;left = mid + 1;  // 尝试更大的盘子数量} else {// 如果不能到达,说明mid过大,需要尝试更小的值right = mid - 1;}}// 输出最后找到的最大盘子数量System.out.println(result);}/*** 判断是否可以带至少k个盘子,在不超过T秒的情况下从(1,1)到达(n,n)* @param k: 假设要带的盘子数量* @return: 是否可以在T秒内到达终点*/private static boolean canReach(int k) {// 使用队列进行广度优先搜索(BFS)Queue<int[]> queue = new LinkedList<>();// 用一个二维数组visited来标记某个位置是否被访问过,防止重复搜索boolean[][] visited = new boolean[n][n];// 起点是(0, 0),即(1,1)的位置,初始时间为0queue.offer(new int[]{0, 0, 0});visited[0][0] = true;  // 标记起点已经访问过// 开始BFS搜索while (!queue.isEmpty()) {int[] current = queue.poll();  // 取出队列中的当前点int x = current[0], y = current[1], time = current[2]; // 当前的x, y坐标和已消耗的时间// 如果已经超过时间限制,继续检查下一个可能的位置if (time > T) {continue;}// 如果已经到达终点(n-1, n-1),返回true,表示带k个盘子可以成功到达if (x == n - 1 && y == n - 1) {return true;}// 向四个方向移动,分别是:下、上、右、左for (int i = 0; i < 4; i++) {int nx = x + dx[i];  // 新的x坐标int ny = y + dy[i];  // 新的y坐标// 检查新位置是否在二维平面内,并且没有访问过if (nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny]) {// 检查新位置是否允许带k个盘子,起点和终点没有限制(值为-1)if (grid[nx][ny] == -1 || grid[nx][ny] >= k) {// 标记新位置为已访问,并加入队列继续搜索visited[nx][ny] = true;queue.offer(new int[]{nx, ny, time + 1});  // 时间加1}}}}// 如果搜索结束还没能到达终点,返回falsereturn false;}
}

http://www.ppmy.cn/server/134234.html

相关文章

基于知识图的电影推荐系统

&#x1f3ac; 毕设灵感——“基于知识图谱的电影推荐系统”&#x1f680; &#x1f449; 如果你的毕业设计还没有灵感&#xff0c;那么这个基于知识图谱的电影推荐系统绝对值得参考&#xff01;这不是普通的推荐系统&#xff0c;而是通过知识图谱大数据的结合&#xff0c;来为…

一、python基础

python基础 认识Python1. Python介绍1.1 为什么学习Python1.2 Python发展历史 2. 语言分类简介2.1 编译型2.2 解释型 Python环境搭建1. Python 解释器1.1 Python解释器下载1.2 Python解释器安装 2. 解释器运行Python脚本2.1 演练步骤 PyCharm1. PyCharm介绍2. PyCharm安装3. Py…

前端开发设计模式——命令模式

目录 一、命令模式的定义和特点 1.定义&#xff1a; 2. 特点&#xff1a; 二、命令模式的结构与原理 1.结构&#xff1a; 2.原理&#xff1a; 三、命令模式的实现方式 1.定义接口命令&#xff1a; 2.创建具体的命令类&#xff1a; 3.定义接收者&…

模拟退火算法:原理与Python实现

模拟退火算法&#xff1a;原理与Python实现 模拟退火算法&#xff08;Simulated Annealing&#xff0c;SA&#xff09;是一种用于全局优化问题的随机算法&#xff0c;尤其适用于大规模、复杂的组合优化问题。该算法受启发于物理冶金学中的退火过程&#xff0c;通过缓慢降低系统…

【Flutter】Dart:流程控制语句

在 Dart 编程中&#xff0c;流程控制语句决定了程序的执行顺序和流程。掌握这些语句可以帮助开发者根据不同条件进行分支决策、执行重复任务、控制代码跳转等。本文将详细介绍 Dart 中的流程控制语句&#xff0c;涵盖分支语句、循环语句和跳转语句。 分支语句 分支语句允许程…

SpringBoot驱动的车辆信息管理平台

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【办公类-57-01】美工室材料报销EXCEL表批量插入截图(图片)

背景需求&#xff1a; 我们班分到美工室&#xff0c;需要准备大量材料&#xff0c;根据原始的报销单EXCLE&#xff0c;里面有商品名称、图片、链接、单位、数量等信息 今天我和搭档一起填写新表&#xff0c;发现手机截图的图片插入EXCEL后非常大&#xff0c; 需要手动调整图片…

Android studio中排除文件功能的小总结

刚开始发现android studio的sourceSets的main下面java的excludes无效&#xff0c;改了好多次都没成功&#xff0c;以为关键字不支持&#xff0c;或者是gradle版本问题&#xff0c;结果查了半天没成功。后来经过对比发现是相对路径问题。 在此总结一下&#xff0c;希望节省大家…