最大子矩阵(信息学奥赛一本通 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

### 关于信息学奥赛一本题目1339的解法 对于信息学奥赛一本中的题目1339,该题目的名称为“最大子矩阵”。这道题目要求在一个给定的整数矩阵找到一个子矩阵,使得这个子矩阵内所有元素最大。 为了求解这个问题,可以采用动态规划的方法来解决。具体来说,可以过枚举上下边界的方式将二维问题转化为一维的最大连续子序列的问题。下面是一个具体的实现方案: #### 动态规划思路 过固定上边界i并逐步增加下边界j,在每次更新时计算当前范围内每一列的累加值sum[k] (k代表第k列),这样就得到了一个新的数组sum[]。此时原问题转化成了在一维数组sum[]里寻找最大的连续子段的问题[^1]。 #### C++代码示例 ```cpp #include <iostream> #include <algorithm> using namespace std; const int MAXN = 105; int mat[MAXN][MAXN]; int sum[MAXN]; // 计算一维数组的最大子序函数 int maxSubArraySum(int arr[], int size) { int max_so_far = INT_MIN, max_ending_here = 0; for (int i = 0; i < size; i++) { max_ending_here += arr[i]; if (max_so_far < max_ending_here) max_so_far = max_ending_here; if (max_ending_here < 0) max_ending_here = 0; } return max_so_far; } void solve() { int N; cin >> N; // 输入矩阵数据 for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j) cin >> mat[i][j]; int result = INT_MIN; // 枚举上下边界的组合 for (int top = 1; top <= N; ++top) { fill(sum + 1, sum + N + 1, 0); // 初始化每列累积值 for (int bottom = top; bottom <= N; ++bottom) { // 更新当前范围内的各列累计值 for (int k = 1; k <= N; ++k) sum[k] += mat[bottom][k]; // 使用 Kadane's Algorithm 寻找最大子阵列 result = max(result, maxSubArraySum(sum, N)); } } cout << "Max Sum of Submatrix is: " << result << endl; } ``` 这段程序首先定义一个辅助函数`maxSubArraySum()`用于处理转换后的一维数组上的最大连续子序列查询;接着在外层循环遍历所有的可能矩形区域,并调用上述函数获取这些区域内元素最大值作为最终的结果输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值