最大矩阵的和

最大矩阵的和

真题目录: 点击去查看

E 卷 100分题型

题目描述

给定一个二维整数矩阵,要在这个矩阵中选出一个子矩阵,使得这个子矩阵内所有的数字和尽量大,我们把这个子矩阵称为和最大子矩阵,子矩阵的选取原则是原矩阵中一块相互连续的矩形区域。

输入描述

输入的第一行包含2个整数n, m(1 <= n, m <= 10),表示一个n行m列的矩阵,下面有n行,每行有m个整数,同一行中,每2个数字之间有1个空格,最后一个数字后面没有空格,所有的数字的在[-1000, 1000]之间。

输出描述

输出一行一个数字,表示选出的和最大子矩阵内所有的数字和。

用例1

输入

3 4
-3 5 -1 5
2 4 -2 4
-1 3 -1 3

输出

20

说明

一个3*4的矩阵中,后面3列的子矩阵求和加起来等于20,和最大。

题解

思路:将二维的问题转换为一维的问题。

  • 转换思路:最终选择的矩阵行数肯定是[1, n]。枚举出选择任意行的情况。选择多行时将同一列进行相加变成一行。
  • 问题就变成了在一行中求最大连续子数组了。最大子数组的状态转移方程:dp[i] = max(dp[i-1], 0) + nums[i]。
  • 记录每种情况下的连续子数组和最大值,其中的最大值就是结果。

c++

#include <iostream>
#include <vector>
#include <climits>
using namespace std;

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int getResult(int n, int m, vector<vector<int>>& matrix);
int maxSubArraySum(vector<int>& nums);
vector<int> matrixZip(int rowFrom, int rowTo, int cols, vector<vector<int>>& matrix);

int main() {
    int n, m;
    cin >> n >> m;

    vector<vector<int>> matrix(n, vector<int>(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> matrix[i][j];
        }
    }

    cout << getResult(n, m, matrix) << endl;
    return 0;
}

int getResult(int n, int m, vector<vector<int>>& matrix) {
    int ans = INT_MIN;

    for (int i = 0; i < n; i++) {
        ans = MAX(ans, maxSubArraySum(matrix[i])); // 单行最大子数组和

        for (int j = i + 1; j < n; j++) {
            vector<int> compressed = matrixZip(i, j, m, matrix);
            ans = MAX(ans, maxSubArraySum(compressed)); // 多行子矩阵最大和
        }
    }
    return ans;
}

int maxSubArraySum(vector<int>& nums) {
    int res = nums[0];
    int dp = nums[0];
    
    for (size_t i = 1; i < nums.size(); i++) {
        dp = MAX(dp, 0) + nums[i];
        res = MAX(res, dp);
    }
    return res;
}

vector<int> matrixZip(int rowFrom, int rowTo, int cols, vector<vector<int>>& matrix) {
    vector<int> zip(cols, 0);
    
    for (int c = 0; c < cols; c++) {
        for (int r = rowFrom; r <= rowTo; r++) {
            zip[c] += matrix[r][c];
        }
    }
    return zip;
}

JAVA

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt();
    int m = sc.nextInt();

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

    System.out.println(getResult(n, m, matrix));
  }

  public static int getResult(int n, int m, int[][] matrix) {
    ArrayList<Integer> dp = new ArrayList<>();

    for (int i = 0; i < n; i++) {
      dp.add(maxSubArraySum(matrix[i])); // 一行子矩阵最大和

      for (int j = i + 1; j < n; j++) {
        dp.add(maxSubArraySum(matrixZip(Arrays.copyOfRange(matrix, i, j + 1)))); // 多行子矩阵最大和
      }
    }

    return dp.stream().max((a, b) -> a - b).orElse(0); // 求出最大和
  }

  // 最大子数组和求解
  public static int maxSubArraySum(int[] nums) {
    int[] dp = new int[nums.length];

    int res = dp[0] = nums[0];

    for (int i = 1; i < nums.length; i++) {
      dp[i] = Math.max(dp[i - 1], 0) + nums[i];
      res = Math.max(res, dp[i]);
    }

    return res;
  }

  // 多行子矩阵,压缩为一行子数组
  public static int[] matrixZip(int[][] matrix) {
    int cols = matrix[0].length;
    int rows = matrix.length;
    int[] zip = new int[cols];

    for (int c = 0; c < cols; c++) {
      for (int r = 0; r < rows; r++) {
        zip[c] += matrix[r][c];
      }
    }

    return zip;
  }
}

Python

# 输入获取
n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for i in range(n)]


# 最大子数组和求解
def maxSubArraySum(nums):
    dp = [0 for i in range(len(nums))]
    res = dp[0] = nums[0]

    for i in range(1, len(nums)):
        dp[i] = max(dp[i - 1], 0) + nums[i]
        res = max(res, dp[i])

    return res


# 将多行子矩阵,压缩为一维数组
def matrixZip(matrix):
    cols = len(matrix[0])
    rows = len(matrix)
    zip = [0 for i in range(cols)]

    for c in range(cols):
        for r in range(rows):
            zip[c] += matrix[r][c]

    return zip


# 算法入口
def getResult(n, m, matrix):
    dp = []

    for i in range(n):
        dp.append(maxSubArraySum(matrix[i]))
        for j in range(i + 1, n):
            dp.append(maxSubArraySum(matrixZip(matrix[i:j + 1])))

    dp.sort()

    return dp[-1]


# 算法调用
print(getResult(n, m, matrix))

JavaScript

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

let lines = [];
let n, m;
rl.on("line", (line) => {
  lines.push(line);

  // 输入第一行时,提取出m、n
  if (lines.length === 1) {
    [n, m] = lines[0].split(" ").map((ele) => parseInt(ele));
  }

  // 输入第一行后,再输入n行时,则开始启动算法程序
  if (lines.length - 1 === n) {
    // 干掉第一行输入,即lines中存储的全是就是matrix要素
    lines.shift();

    // matrix是算法程序的入参二维数组
    let matrix = [];
    // 将多行输入的matrix要素提取出来存到二维数组中
    lines.forEach((line) => {
      matrix.push(
        line
          .split(" ")
          .map((ele) => parseInt(ele))
          .slice(0, m)
      );
    });

    // 调用算法程序
    console.log(maxSubMatrixSum(matrix));

    // 将输入归0,重新接收下一轮
    lines.length = 0;
  }
});

function maxSubMatrixSum(matrix) {
  let dp = [];
  for (let i = 0; i < matrix.length; i++) {
    dp.push(maxSubArraySum(matrix[i]));

    for (let j = i + 1; j < matrix.length; j++) {
      dp.push(maxSubArraySum(matrixZip(matrix.slice(i, j + 1))));
    }
  }

  return dp.sort((a, b) => b - a)[0];
}

function maxSubArraySum(nums) {
  let dp = new Array(nums.length);

  let result = (dp[0] = nums[0]);

  for (let i = 1; i < nums.length; i++) {
    dp[i] = Math.max(dp[i - 1], 0) + nums[i];
    result = Math.max(result, dp[i]);
  }

  return result;
}

function matrixZip(matrix) {
  let cols = matrix[0].length;
  let rows = matrix.length;
  let zip = new Array(cols).fill(0);

  for (let c = 0; c < cols; c++) {
    for (let r = 0; r < rows; r++) {
      zip[c] += matrix[r][c];
    }
  }

  return zip;
}

Go

package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

// 获取最大子矩阵和
func getResult(n, m int, matrix [][]int) int {
	ans := math.MinInt32

	for i := 0; i < n; i++ {
		ans = max(ans, maxSubArraySum(matrix[i])) // 单行最大子数组和

		for j := i + 1; j < n; j++ {
			compressed := matrixZip(i, j, m, matrix)
			ans = max(ans, maxSubArraySum(compressed)) // 多行子矩阵最大和
		}
	}
	return ans
}

// 最大子数组和(Kadane's Algorithm)
func maxSubArraySum(nums []int) int {
	res, dp := nums[0], nums[0]

	for i := 1; i < len(nums); i++ {
		dp = max(dp, 0) + nums[i]
		res = max(res, dp)
	}
	return res
}

// 多行子矩阵,压缩为一行
func matrixZip(rowFrom, rowTo, cols int, matrix [][]int) []int {
	zip := make([]int, cols)

	for c := 0; c < cols; c++ {
		for r := rowFrom; r <= rowTo; r++ {
			zip[c] += matrix[r][c]
		}
	}
	return zip
}

// 获取最大值
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	// 读取输入
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	line := scanner.Text()
	parts := strings.Fields(line)
	n, _ := strconv.Atoi(parts[0])
	m, _ := strconv.Atoi(parts[1])

	// 读取矩阵
	matrix := make([][]int, n)
	for i := 0; i < n; i++ {
		matrix[i] = make([]int, m)
		scanner.Scan()
		rowValues := strings.Fields(scanner.Text())
		for j := 0; j < m; j++ {
			matrix[i][j], _ = strconv.Atoi(rowValues[j])
		}
	}

	// 计算结果并输出
	fmt.Println(getResult(n, m, matrix))
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量

嘿&#xff0c;朋友们&#xff01;喜欢这个并查集的讲解吗 记得点个关注哦&#xff0c;让我们一起探索算法的奥秘&#xff0c;别忘了一键三连&#xff0c;你的支持是我最大的动力&#xff01; 欢迎拜访&#xff1a;羑悻的小杀马特.-CSDN博客 本篇主题&#xff1a;深度剖析并查…

Jupyter Lab的使用

Lab与Notebook的区别: Jupyter Lab和Jupyter notebook有什么区别&#xff0c;这里找到一篇博客不过我没细看&#xff0c; Jupyter Lab和Jupyter Notebook的区别 - codersgl - 博客园 使用起来Lab就是一个更齐全、功能更高级的notebook&#xff0c; 启用滚动输出: 有时候一个…

C++【深入 STL--list 之 迭代器与反向迭代器】

接前面的手撕list(上)文章&#xff0c;由于本人对于list的了解再一次加深。本文再次对list进行深入的分析与实现。旨在再一次梳理思路&#xff0c;修炼代码内功。 1、list 基础架构 list底层为双向带头循环链表&#xff0c;问题是如何来搭建这个list类。可以进行下面的考虑&am…

Games104——游戏引擎Gameplay玩法系统:基础AI

这里写目录标题 寻路/导航系统NavigationWalkable AreaWaypoint NetworkGridNavigation Mesh&#xff08;寻路网格&#xff09;Sparse Voxel Octree Path FindingDijkstra Algorithm迪杰斯特拉算法A Star&#xff08;A*算法&#xff09; Path Smoothing Steering系统Crowd Simu…

2024最新版Node.js详细安装教程(含npm配置淘宝最新镜像地址)

一&#xff1a;Node.js安装 浏览器中搜索Nodejs&#xff0c;或直接用网址:Node.js — 在任何地方运行 JavaScript 建议此处下载长期支持版本&#xff08;红框内&#xff09;: 开始下载&#xff0c;完成后打开文件: 进入安装界面&#xff0c;在此处勾选&#xff0c;再点击n…

高效 MyBatis SQL 写法一

高效 MyBatis SQL 写法一 前言 MyBatis 作为一款优秀的持久层框架&#xff0c;极大地简化了数据库操作。 然而&#xff0c;在实际开发中&#xff0c;XML 配置的编写仍然可能显得繁琐。 本文将分享一些 MyBatis 动态 SQL 的优质写法&#xff0c;帮助开发者提升效率并减少错误…

C语言按位取反【~】详解,含原码反码补码的0基础讲解【原码反码补码严格意义上来说属于计算机组成原理的范畴,不过这也是学好编程初级阶段的必修课】

目录 概述【适合0基础看的简要描述】&#xff1a; 上述加粗下划线的内容提取版&#xff1a; 从上述概述中提取的核心知识点&#xff0c;需背诵&#xff1a; 整数【包含整数&#xff0c;负整数和0】的原码反码补码相互转换的过程图示&#xff1a; 过程详细刨析&#xff1a;…

如何安装PHP依赖库 更新2025.2.3

要在PHP项目中安装依赖&#xff0c;首先需要确保你的系统已经安装了Composer。Composer是PHP的依赖管理工具&#xff0c;它允许你声明项目所需的库&#xff0c;并管理它们。以下是如何安装Composer和在PHP项目中安装依赖的步骤&#xff1a; 一. 安装Composer 对于Windows用户…

【通俗易懂说模型】线性回归(附深度学习、机器学习发展史)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …

硬件电路基础

目录 1. 电学基础 1.1 原子 1.2 电压 1.3 电流 1.电流方向&#xff1a; 正极->负极,正电荷定向移动方向为电流方向&#xff0c;与电子定向移动方向相反。 2.电荷&#xff08;这里表示负电荷&#xff09;运动方向&#xff1a; 与电流方向相反 1.4 测电压的时候 2. 地线…

【含文档+PPT+源码】基于Python爬虫二手房价格预测与可视化系统的设计与实现

项目介绍 本课程演示的是一款基于Python爬虫二手房价格预测与可视化系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该项…

【数据结构】树哈希

目录 一、树的同构1. 定义2. 具体理解(1) 结点对应(2) 孩子相同(3) 递归性质 3. 示例 二、树哈希1.定义2.哈希过程&#xff08;1&#xff09;叶节点哈希&#xff08;2&#xff09;非叶节点哈希&#xff08;3&#xff09;组合哈希值 3.性质&#xff08;1&#xff09; 唯一性 \re…

渗透测试之文件包含漏洞 超详细的文件包含漏洞文章

目录 说明 通常分为两种类型&#xff1a; 本地文件包含 典型的攻击方式1&#xff1a; 影响&#xff1a; 典型的攻击方式2&#xff1a; 包含路径解释&#xff1a; 日志包含漏洞&#xff1a; 操作原理 包含漏洞读取文件 文件包含漏洞远程代码执行漏洞: 远程文件包含…

Mysql:数据库

Mysql 一、数据库概念&#xff1f;二、MySQL架构三、SQL语句分类四、数据库操作4.1 数据库创建4.2 数据库字符集和校验规则4.3 数据库修改4.4 数据库删除4.4 数据库备份和恢复其他 五、表操作5.1 创建表5.2 修改表5.3 删除表 六、表的增删改查6.1 Create(创建):数据新增1&#…

ChatGPT怎么回事?

纯属发现&#xff0c;调侃一下~ 这段时间deepseek不是特别火吗&#xff0c;尤其是它的推理功能&#xff0c;突发奇想&#xff0c;想用deepseek回答一些问题&#xff0c;回答一个问题之后就回复服务器繁忙&#xff08;估计还在被攻击吧~_~&#xff09; 然后就转向了GPT&#xf…

Vue 中如何嵌入可浮动的第三方网页窗口(附Demo)

目录 前言1. 思路Demo2. 实战Demo 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 1. 思路Demo 以下Demo提供思路参考&#xff0c;需要结合实际自身应用代码 下述URL的链接使用百度替代&#xff01; 方式 1…

【Linux】23.进程间通信(2)

文章目录 3. 进程间通信3.1 进程间通信介绍3.1.1 进程间通信目的3.1.2 进程间通信发展 3.2 什么是进程间通信3.3 管道3.4 匿名管道pipe()3.4.1 站在文件描述符角度-深度理解管道3.4.2 站在内核角度-管道本质3.4.3 用fork来共享管道原理3.4.5 管道相关知识3.4.6 代码一&#xff…

AI大模型开发原理篇-8:Transformer模型

近几年人工智能之所以能迅猛发展&#xff0c;主要是靠2个核心思想&#xff1a;注意力机制Attention Mechanism 和 Transformer模型。本次来浅谈下Transformer模型。 重要性 Transformer模型在自然语言处理领域具有极其重要的地位&#xff0c;为NLP带来了革命性的突破‌。可以…

html2canvas绘制页面并生成图像 下载

1. 简介 html2canvas是一个开源的JavaScript库&#xff0c;它允许开发者在用户的浏览器中直接将HTML元素渲染为画布&#xff08;Canvas&#xff09;&#xff0c;并生成图像。以下是对html2canvas的详细介绍&#xff1a; 2. 主要功能 html2canvas的主要功能是将网页中的HTML元…

基于RK3588/RK3576+MCU STM32+AI的储能电站电池簇管理系统设计与实现

伴随近年来新型储能技术的高质量规模化发展&#xff0c;储能电站作为新能源领域的重要载体&#xff0c; 旨在配合逐步迈进智能电网时代&#xff0c;满足电力系统能源结构与分布的创新升级&#xff0c;给予相应规模 电池管理系统的设计与实现以新的挑战。同时&#xff0c;电子系…