最大子矩阵(信息学奥赛一本通 1224)

【题目描述】

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1×1)子矩阵。

【输入】

输入是一个N×N的矩阵。输入的第一行给出N(0<N≤100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[−127,127]。

【输出】

输出最大子矩阵的大小。

【输入样例】

4

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

【输出样例】

15


首先,如果这道题暴力搜索矩阵的两个端点,再依次计算矩阵和求最大(大致需要六个循环)在ybt上只能得30分,其余都会TLE

那么,我们在暴力的基础上,给这道题加个小小的优化——前缀和(只需四重循环):

关于具体的前缀和思想,请看???

https://www.cnblogs.com/ljy-endl/p/11325425.html

虽然这样呢已经可以过了,但是精益求精的好孩子(对就是我没错)是不会就这样算了,我们进一步在前缀和的基础上加上贪心的思想(三重循环):

这样就感觉肥肠完美 (当然也可能有大佬想出了更加高级的算法)还是当我没说吧...上代码!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[101][101];
 4 int main()
 5 {
 6     int n,max=-1;cin>>n;
 7     for(int i=1;i<=n;i++)
 8     {
 9         for(int j=1;j<=n;j++)
10         {
11             cin>>a[i][j];
12             a[i][j]+=a[i][j-1];
13         }
14     }
15     for(int i=0;i<n;i++)
16     {
17         for(int j=i+1;j<=n;j++)
18         {
19             int ans=0;
20             for(int k=1;k<=n;k++)
21             {
22                 ans+=a[k][j]-a[k][i];
23                 if(ans>max)max=ans;
24                 if(ans<0)ans=0;
25             }
26         }
27     }
28     cout<<max;
29     return 0;
30 }

原文地址:https://www.cnblogs.com/ljy-endl/p/11328369.html

时间: 2024-11-04 11:36:04

最大子矩阵(信息学奥赛一本通 1224)的相关文章

信息学奥赛一本通 5.4 状态压缩动态规划

#loj 10170. 「一本通 5.4 例 1」骑士 看数据范围n<=10,所以不是搜索就是状压dp,又因为搜索会超时所以用dp dp[i][k][j]表示现已经放到第i行,前面共有k个,这一行状态为j so,dp[i][k][j]=dp[i-1][k-num[j]][t] #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cma

【信息学奥赛一本通】第三部分_栈 ex1_4cale (中缀转后缀7符号)

其实这个中缀转后缀是费了很大功夫的,明白算法后第一次实现花了近三小时ORZ #include <stdio.h> #include <string.h> #include <ctype.h> char Mstr[511],Msta[511] = {'@'},Bstr[511]; int sta[511]; const short list[4][4] = {{0,-1,1,1},{1,0,1,1},{1,1,1,-2},{-1,-1,2,1}}; int level (

【信息学奥赛一本通】第三部分_队列 ex2_3produce 产生数

给出一个整数n(n<=2000)(代码可适用n<=10^31)和k个变换规则(k<=15). 规则:1.1个数字可以变换成另1个数字: 2.规则中右边的数字不能为零. BFS 1 #include <stdio.h> 2 #include <string.h> 3 #define maxn 1000 4 5 char num[33]; 6 int len,q[maxn],Visited[11]; 7 long long ans = 1; 8 9 int main

信息学奥赛一本通 5.1 区间类动态规划

石子合并[loj 10147] /* dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) i<=k<j */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int re

信息学奥赛一本通 5.2 树形动态规划

题解在代码中 二叉苹果树[loj 10153] /* 若要留q条边便是要留q+1个点 所以记忆化搜索 dp[pos][ans]=max(dp[pos][ans],dp[l[pos]][k]+dp[r[pos]][ans-k-1]+a[pos]) 0<=k<=ans-1 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<c

信息学奥赛一本通 提高篇 序列第k个数 及 快速幂

我是传送门 这个题首先是先判断是等差还是等比数列 等差的话非常简单: 前后两个数是等差的,举个栗子: 3 6 9 12 这几个数,(我感觉 1 2 3 4并说明不了什么) 每次都加3嘛,很容易看出,第一个数是3 * 1,第二个是3 * 2....以此类推 第k个数 = (第2个数 - 第1个数) * k ; (z - y) * k % 200907 % 200907 的原因是题目要求 但是这样并不能过 hack一下 4 7 10 13 用原先的公式:(7 - 4) * 4 % 200907 =

【信息学奥赛一本通 提高组】第二章 二分与三分

一.二分 二分法,在一个单调有序的集合或函数中查找一个解,每次分为左右两部分,判断解在那个部分并调整上下界,直到找到目标元素,每次二分都将舍弃一般的查找空间,因此效率很高. 二分常见模型 1.二分答案 最小值最大(或是最大值最小)问题,这类双最值问题常常选用二分法求解,也就是确定答案后,配合贪心,DP等其他算法检验这个答案是否合理,将最优化问题转化为判定性问题.例如,将长度为n的序列ai分为最多m个连续段,求所有分法中每段和的最大值的最小是多少? 2.二分查找 用具有单调性的布尔表达式求解分界点

求后序遍历(信息学奥赛一本通 1339)

假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道. PreOrder: GDAFEMHZ InOrder: ADEFGHMZ PostOrder: AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是"GDAFEMHZ",而中序遍历是"ADEFGHMZ"应该如何求后续遍历? 第一步,root最简单,前序遍历的第一节点G就是root. 第二步,继续观察前序遍历GDAFEMHZ,除了知道G是root,

樱花(信息学奥赛一本通 1624)

[题目描述] 原题来自:HackerRank Equations 求不定方程: 1/x + 1/y = 1/n! 的正整数解 (x,y)的数目. [输入] 一个整数 n. [输出] 一个整数,表示有多少对 (x,y) 满足题意.答案对 109+7 取模. [输入样例] 2 [输出样例] 3 [提示] 样例说明 共有三个数对 (x,y) 满足条件,分别是 (3,6),(4,4) 和 (6,3). 数据范围与提示: 对于 30% 的数据,n≤100: 对于全部数据,1≤n≤106 . (这里不得不吐