标签:
一.题目
输入一个二维整形数组,数组里有正数也有负数。
求所有子数组的和的最大值。
二.设计思想
第一种方法:首先若要对二维数组进行分析,通常想要把它化简成为一个一维数组。再先求每个一维数组的最大子数组和,并记下每行最大一维子数组的下标。这是就会分两种情况:第一种是行之间的最大子数组是相连的,这时就可以直接相加得到;第二种是不相连的,,这时候就把每行的最大子数组看成一个整体,再使每个最大数组块进行相连,求使其相连的最小代价。最后得到的就是最大联通子数组的和。
第二种方法:在二维整形数组中,数据可能会有正也有负,要求最大值,我们重点关注正数,所以要首先判断二维数组中哪些位置上的数是正数,利用另一个二维数组记录正数的位置,然后判断哪些数是连通的。首先定位这个二维数组中的最大值,然后在分析这个值周围的4个数,联通这4个数中的正数,若全为负数,则查找次大值,并与最大值联通,判断联通前与联通后值得大小,若变小则不联通最大值,若变大则联通最大值,以此类推,直到最大联通子数组怎么联通都比原来的值小。
三.实验代码
#include<iostream>
#include<fstream>
using namespace std;
# define N 100
int zuida(int n, int a[], int *p, int *q)//一维数组的最大子数组和
{
int b[N] = { 0 };
int i, sum1 = 0, max1 = 0;
for (i = 0; i<n; i++)
{
if (sum1<0)
{
sum1 = a[i];
}
else
{
sum1 = sum1 + a[i];
}
b[i] = sum1;
}
max1 = b[0];
for (i = 0; i<n; i++)
{
if (max1<b[i])
{
max1 = b[i];
*q = i; //记录最大子数组的终点位置
}
}
for (i = *q; i >= 0; i--)
{
if (b[i] == a[i])
{
*p = i;//记录最大子数组的起点
break;
}
}
return max1;
}
int main()
{
int m1, m2, i, j, p, q, t2;
int sum, max;
int left[N], right[N], t[N];
int a[N][N], b[N];
ifstream fin("sz.txt");
ifstream fin1("sz1.txt");
fin1 >> m1 >> m2;
cout << "二维数组的行和列为"<< endl;
cout << m1 << " " << m2 << endl;
for (int i = 0; i < m1; i++)
for (int j = 0; j < m2; j++)
{
fin >> a[i][j];
}
cout << "TXT文件中的二维数组为" << endl;
for (int i = 0; i < m1; i++)
{
for (int j = 0; j < m2; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
for (i = 0; i<m1; i++)//求每一行最大子数组
{
for (j = 0; j<m2; j++)
{
b[j] = a[i][j];
}
sum = zuida(m1, b, &p, &q);
left[i] = p; //记录最大子数组的坐标位置
right[i] = q;
t[i] = sum;
}
t2 = t[0];
for (i = 0; i + 1<m2; i++)//将最大子数组合并
{
if (left[i] <= right[i + 1] && right[i] >= left[i + 1])//两行的最大子数组块相连
{
t2 += t[i + 1];
}
for (j = left[i]; j<left[i + 1]; j++)
{
if (a[i + 1][j]>0)
t2 += a[i + 1][j]; //判别独立正数
}
}
cout <<"最大子数组和为:"<< t2 << endl;
return 0;
}
实验总结:
通过这次试验,我们考虑到了更多的细节问题,由一维数组转换到二维数组,需要更多的考虑。
标签:
原文地址:http://www.cnblogs.com/zjj123456/p/5360266.html