最大联通子数组的和

最大联通子数组的和

 在几次“迭代”开发数组的项目之后老师又布置了这个“联通数组”的任务,当然,此次任务依旧是“结对编程”,要求如下:

1、题目:返回一个二维数整数组中最大联通子数组的和;

2、数组中有正数,也有负数;

3、求所有子数组的最大值,要求时间复杂度为O(n);

4、程序要使用的数组放在input.txt文件中,文件的格式:行数,列数,每一行的元素;


一、实验思路 

      数组的行和列和数组元素又文件读入,然后把数按行分成几个一维数组,对于该一维数组,求出他们的最大连续数组之和,并且记录下最大连续数组的第一位和最后一位的位置,之后判断几个一维数组的最大连续数组的位置是否相接或包括。最后在加上没有包括的正数(必须在上一行的最大连续数组的第一位和最后一位的位置之间),输出之前加和。

二、实验代码及实现

代码如下:

  1 //2016/4/1 求最大联通子数组的和——赵子茵&孔宇航
  2 
  3 #include<iostream>
  4 #include<fstream>
  5 using namespace std;
  6 
  7 int Max(int n, int arr[], int *Start_mark, int *Final_mark)
  8 {
  9     int step[100] = { 0 };//Step记录每步计算子数组的和
 10     int i, sum = 0, max1 = 0;
 11     /* sum是子数组的和
 12        max1是子数组最大和
 13     */
 14     for (i = 0; i<n; i++)
 15     {
 16         if (sum<0)
 17             sum = arr[i];
 18         else
 19             sum = sum + arr[i];
 20         step[i] = sum;
 21     }
 22     max1 = step[0];
 23     for (i = 0; i<n; i++)
 24     {
 25         if (max1<step[i])
 26         {
 27             max1 = step[i];
 28             *Final_mark = i;
 29         }
 30     }
 31     for (i = *Final_mark; i >= 0; i--)
 32     {
 33         if (step[i] == arr[i])
 34         {
 35             *Start_mark = i;
 36             break;
 37         }
 38     }
 39     return max1;
 40 }
 41 
 42 void main()
 43 {
 44     int m, n, i, j, Start_mark, Final_mark, big;
 45     int Max1;
 46     int read[10000];//读取文件的字符集
 47     int up[100], down[100], h[100];
 48     int Arr2[100][100], Arr1[100];
 49     /* m行n列的数组
 50        Start_mark表示最大子数组的起始坐标
 51        Final_mark表示最大子数组的终止坐标
 52        big表示最后输出的最大联通子数组和
 53        Max1是函数返回的一维数组最大子数组和
 54        up存放每行最大子数组起始坐标
 55        down存放每行最大子数组终止坐标
 56        h存放每行最大子数组的和
 57        Arr2存放二维数组
 58        Arr1存放拆成的一维数组
 59     */
 60 
 61     /*cout << "请输入二维数组的行数和列数:";
 62     cin >> m >> n;
 63     cout << "请输入这个二维矩阵:" << endl;
 64     for (i = 0; i<m; i++)
 65     {
 66         for (j = 0; j<n; j++)
 67         {
 68             cin >> a[i][j];
 69         }
 70     }*/
 71 
 72     //文件输入
 73     ifstream infile("input.txt", ios::in);
 74     if (infile.is_open() == false)
 75     {
 76         cerr << "open error!" << endl;
 77         exit(1);
 78     }
 79     infile >> read[0];//读取行数m
 80     m = read[0];
 81     infile >> read[1];//读取列数n
 82     n = read[1];
 83     cout << "指定文件中" << read[0] << "" << read[1] << "列的二维数组如下:" << endl;
 84     for (i = 0; i < m; i++)//读取数组并按格式输出
 85     {
 86         for (j = 0; j < n; j++)
 87         {
 88             infile >> read[i + 2];
 89             Arr2[i][j] = read[i + 2];
 90             cout << Arr2[i][j] << " ";
 91             if (j % (n - 1) == 0 && j != 0)
 92                 //if (j == n-1)
 93                 cout << endl;
 94         }
 95     }
 96     infile.close();
 97 
 98     //把二维数组按行分解为几个一维数组
 99     for (i = 0; i<m; i++)
100     {
101         for (j = 0; j<n; j++)
102         {
103             Arr1[j] = Arr2[i][j];
104         }
105         Max1 = Max(n, Arr1, &Start_mark, &Final_mark);
106         up[i] = Start_mark;
107         down[i] = Final_mark;
108         h[i] = Max1;
109     }
110 
111     big = h[0];
112     for (i = 0; i + 1<m; i++)
113     {
114         if (up[i] <= down[i + 1] && down[i] >= up[i + 1])//联通,则相加
115             big += h[i + 1];
116         for (j = up[i]; j<up[i + 1]; j++)
117         {
118             if (Arr2[i + 1][j]>0)//是否独立正数,有则加
119                 big += Arr2[i + 1][j];     
120         }
121     }
122 
123     cout << "此二维数组的最大联通子数组的和为:" << endl;
124     cout << big << endl;
125     
126 }

运行结果如下:

      

    

     

三、实验心得体会

      对于本次实验,我们最开始尝试过遍历数组的方法,设置了结构体,将数组的数设置坐标,但是后来没有掌握好方法以失败告终。在课堂上受到同学的启发将二维数组编程一位数组,比如第一行和第二行加和后出现新的一位数组的方法,在网上阅读了写别人的思路,最后和小伙伴写出了这个程序。这个程序存在缺陷,个别的测试用例会出错,现在的程序只能解决最大连续数组相连的,还不能解决不相连的,对于最后今加上剩余的正数,只会加上与第一行重合的,第三行以及以下的行并不加上前一步加上的第二行的正数。这个缺陷会在以后慢慢完善,希望老师谅解。

最后附 孔同学(孔宇航)博客地址:http://www.cnblogs.com/kongyuhang/

Keyboard not found...press F1 to continue:)
原文地址:https://www.cnblogs.com/2016helen/p/5352919.html