您的位置:首页 > 其它

nyoj 44 子串和 & nyoj 104 最大和

2015-03-04 10:19 155 查看


子串和

时间限制:5000 ms | 内存限制:65535 KB
难度:3

描述给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。

输入第一行是一个整数N(N<=10)表示测试数据的组数)

每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),表示数列中的所有元素。(0<n<=1000000)
输出对于每组测试数据输出和最大的连续子串的和。
样例输入
1
5
1 2 -1 3 -2


样例输出
5


一道需要很注意的题。用的是贪心策略:用max保存一段区间的最大值。一边输入一边看看当前连续区间的和sum是不是大于了max,如果大了,就更新max。注意,此时的sum没有被更新,而是继续累加。这样就完成了连续区间这一要求。 可能会问:这样求的不是从第一个数开始的最大子串和么? 如果是从第二数开始的某一子串和才是最大的怎么办?这时,就要想:这些全都是数啊,如果都是正数,肯定全加起来才是最大的。但问题就是这里边会有负数。所以,从第i开始的子串和最大的情况,只可能是前i-1个数的和为负数,不然不可能舍弃这一段数的。

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int a[1000003];
int main()
{
int t, n, i, sum, max;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
scanf("%d", &a[0]);
sum = a[0];
max = a[0];//max一定要足够小。因为可能有负数。
if(sum < 0)//这个一定要有,不然输入-2,1……就会出错,1不能被存入了。
sum = 0;
for(i = 1 ; i < n ; i++)
{
scanf("%d", &a[i]);
sum += a[i];
if(sum > max)
max = sum;
if(sum < 0)
sum = 0;
}
printf("%d\n", max);

}
return 0;
}



最大和

时间限制:1000 ms | 内存限制:65535 KB
难度:5

描述

给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。

例子:

0 -2 -7 0

9
2 -6 2

-4
1 -4 1

-1 8 0 -2

其最大子矩阵为:

9
2

-4
1

-1
8

其元素总和为15。

输入第一行输入一个整数n(0<n<=100),表示有n组测试数据;

每组测试数据:

第一行有两个的整数r,c(0<r,c<=100),r、c分别代表矩阵的行和列;

随后有r行,每行有c个整数;

输出输出矩阵的最大子矩阵的元素之和。
样例输入
1
4 4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2


样例输出
15


利用上一题的思想,这一题也可以用类似的贪心解出来。

乍眼一看,这题和上一题差不多啊,但是怎么把二维转化为一维呢?因为要想办法把矩阵转化为一行的这种数组,所以就想到压缩,假如要求一个两行的矩阵的最大子矩阵,那么就可以先求出第一行的最大子串和,然后把数组一列对一列地叠加,更新后的t再求最大子串和,就是以第一行起始的所有矩阵的最大子矩阵了,因为最大子矩阵就是数字加起来和最大!

用i控制总循环次数,表示:这一次求的是起始行必为i,但终止行(j)和宽度(k)随意的所有矩形中最大的。这里矩形数字和的求法是在同i的条件下,用t数组保存一行,即把上几行的数组压缩成一个t,像摞饼一样- - 一层一层叠加上,列于列对应,然后求t的最大子串和,也就是被压缩的矩阵中的最大矩阵。然后求以所有起始行开始的所有最大值中的最大值即为所求。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int r, c, a[105][105];
int findmax(int t[])
{
int max = t[1], sum = 0, i;
for(i = 1 ; i <= c ; i++)//必须从1开始。如果从2开始,假如是-2,1……就会出错
{
sum += t[i];
if(sum > max)
max = sum;
if(sum < 0)
sum = 0;
}
return max;
}
int main()
{
int n, i, j, k, max, t[105], s;
scanf("%d", &n);
while(n--)
{
scanf("%d %d", &r, &c);
for(i = 1 ; i <= r ; i++)
for(j = 1 ; j <= c ; j++)
scanf("%d", &a[i][j]);
max = a[1][1];
for(i = 1 ; i <= r ; i++)
{
memset(t, 0, sizeof(t));
for(j = i ; j <= r ; j++)
{
for(k = 1 ; k <= c ; k++)
t[k] = t[k] + a[j][k];
s = findmax(t);
if(s > max)
max = s;
}
}
printf("%d\n", max);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: