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

最多可收集的水果数目

三个小朋友收集水果问题:最大水果收集路径

问题描述

有一个游戏,游戏由 n x n 个房间网格状排布组成。给定一个大小为 n x n 的二维整数数组 fruits,其中 fruits[i][j] 表示房间 (i, j) 中的水果数目。

游戏开始时,三个小朋友分别从角落房间 (0, 0)(0, n - 1)(n - 1, 0) 出发。每个小朋友都会恰好移动 n - 1 次,并到达房间 (n - 1, n - 1)。不同小朋友的移动规则如下:

  1. 第一个小朋友(0, 0) 出发,每次可以选择移动到 (i + 1, j + 1)(i + 1, j)(i, j + 1)(如果存在)。
  2. 第二个小朋友(0, n - 1) 出发,每次可以选择移动到 (i + 1, j - 1)(i + 1, j)(i + 1, j + 1)(如果存在)。
  3. 第三个小朋友(n - 1, 0) 出发,每次可以选择移动到 (i - 1, j + 1)(i, j + 1)(i + 1, j + 1)(如果存在)。

每个小朋友到达一个房间时会收集该房间的所有水果。如果两个或更多小朋友进入同一个房间,则只有一个小朋友能收集该房间的水果,且该房间中的水果在收集后消失。

请你返回三个小朋友总共最多可以收集多少个水果。

示例

示例 1:

输入:

fruits = [[1, 2, 3, 4], [5, 6, 8, 7], [9, 10, 11, 12], [13, 14, 15, 16]]
输出:
100

解释:

第 1 个小朋友(绿色)的移动路径为 (0,0) -> (1,1) -> (2,2) -> (3, 3)。
第 2 个小朋友(红色)的移动路径为 (0,3) -> (1,2) -> (2,3) -> (3, 3)。
第 3 个小朋友(蓝色)的移动路径为 (3,0) -> (3,1) -> (3,2) -> (3,3)。
他们总共能收集 1 + 6 + 11 + 1 + 4 + 8 + 12 + 13 + 14 + 15 = 100 个水果。
在这里插入图片描述

示例 2:
输入:

fruits = [[1, 1], [1, 1]]

输出:

4

解释:

第 1 个小朋友的移动路径为 (0,0) -> (1,1)。
第 2 个小朋友的移动路径为 (0,1) -> (1,1)。
第 3 个小朋友的移动路径为 (1,0) -> (1,1)。
他们总共能收集 1 + 1 + 1 + 1 = 4 个水果。

思路分析

  1. 了解移动规则
    第一个小朋友的路径是沿对角线移动的。因为每个格子只能被收集一次,第二个小朋友的最优路径应该是从 (0, n-1) 移动到 (n-2, n-1),并且不能越过主对角线。因此,最优解中第二个小朋友一定不会碰到主对角线。
    需要特别处理如何从 (n-2, n-1) 出发,并且确保最终能精确到达 (0, n-1)。每次规划路径时,我们需要确保每个小朋友的路径不会重叠,并且他们的水果收集路径最大化。
  2. 边界条件处理
    对于第二个小朋友,最关键的是每次的 j 必须满足 j >= n - 1 - i,确保路径不会越过对角线。
    通过递归和记忆化搜索的方式,计算每个小朋友的最大水果收集数量。
  3. 动态规划实现
    通过递归和记忆化搜索,我们可以解决这个问题。下面是实现代码:
class Solution {
public:int maxCollectedFruits(vector<vector<int>>& fruits) {int n = fruits.size(), res = 0;vector<vector<int>> memo(n, vector<int>(n, -1)); // 记忆化数组// 记忆化搜索函数function<int(int, int)> dfs = [&](int r, int c) -> int {if (r == 0) return fruits[r][c];if (memo[r][c] != -1) return memo[r][c]; // 如果已计算,直接返回for (int i = -1; i <= 1; i++) {int y = c + i;if (y >= n || y < n - 1 - (r - 1)) continue; // 确保列范围合法memo[r][c] = max(memo[r][c], dfs(r - 1, y) + fruits[r][c]);}return memo[r][c];};// 计算第一个小朋友的收集水果for (int i = 0; i < n; i++) {res += fruits[i][i];}res += dfs(n - 2, n - 1); // 从下往上走,第二个小朋友的收集路径// 将下三角形的数据填充到上三角for (int i = 0; i < n; i++) {for (int j = i; j < n; j++) {fruits[i][j] = fruits[j][i];}}// 重置memo数组并计算第三个小朋友的收集路径std::fill_n(memo.begin(), n, std::vector<int>(n, -1));res += dfs(n - 2, n - 1);return res;}
};
  1. 思路总结
    记忆化搜索:通过递归的方式计算每个小朋友的最大水果收集数量,并利用记忆化缓存避免重复计算。
    路径规划:根据每个小朋友的移动规则,避免路径重叠,并确保每个小朋友能够最大化收集水果。
    矩阵转置:对于第二个小朋友和第三个小朋友,可以通过对矩阵进行转置操作,简化计算。
http://www.lryc.cn/news/490965.html

相关文章:

  • 戴尔 AI Factory 上的 Agentic RAG 搭载 NVIDIA 和 Elasticsearch 向量数据库
  • HarmonyOS4+NEXT星河版入门与项目实战(16)------ 状态管理 @State(页面数据刷新与渲染)
  • Origin教程003:数据导入(2)-从文件导入和导入矩阵数据
  • 设计自己的网络通信协议
  • 深入理解 Seata:分布式事务的最佳解决方案
  • JDK下载
  • 如何使用 Python 开发一个简单的文本数据转换为 Excel 工具
  • React(六)——Redux
  • java抽奖系统(二)
  • STM32F10x 定时器
  • 从0开始学PHP面向对象内容之常用设计模式(适配器,桥接,装饰器)
  • 玩转数字与运算:用C语言实现24点游戏的扑克牌魅力
  • 前端入门之VUE--基础与核心
  • logback 初探学习
  • 在Elasticsearch中,是怎么根据一个词找到对应的倒排索引的?
  • 1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据
  • linux实战-黑链——玄机靶场
  • 鸿蒙NEXT开发案例:字数统计
  • uniapp vue2项目迁移vue3项目
  • 16.C++STL 3(string类的模拟,深浅拷贝问题)
  • 神经网络10-Temporal Fusion Transformer (TFT)
  • “iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题
  • 《图像梯度与常见算子全解析:原理、用法及效果展示》
  • 【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓
  • LlamaIndex ollama 搭建本地RAG应用,建立本地知识库
  • draggable的el-dialog实现对话框标题可以选择
  • 2024年Android面试总结
  • 树莓派3:64位系统串口(UART)使用问题的解决方法
  • SemiDrive E3 硬件设计系列---唤醒电路设计
  • 淘宝接口高并发采集核心要点解读,开启电商数据智能应用新纪元