代码改变世界

homework-02

2013-10-01 12:48  adun_li  阅读(241)  评论(3编辑  收藏  举报

      这是我第二次写博客,homework two果真是很难,我听到了同学们的哀怨声,而我也是其中一个,或者说我是一个很菜的选手,这次作业,我一共完成了二维数组求最大子数组的和,水平和垂直方向的连接求和,至于联通的问题,只听到大牛在说什么dp,自己也有一些想法,但是实践起来复杂度很高,就放弃了,由衷的希望老师可以针对这个问题好好讲解一下。

      言归正传,我来说说这次作业的思路,这次我的编写语言是c++,首先是二维数组求最大子数组的和的问题,参考作业一,可以想到把二维数组向一维的方向前进,最朴素的算法时间复杂度是O(n^6),不断优化,可以最终达到O(n^3),基本思路就是创建一个新的二维数组sum[i][t],其中每个元素代表从num[0][0]到num[i][j]所组成的矩阵中所有元素的和,这样在求任意一个矩阵就可以充分利用sum[j][t]-sum[i-1][t]这个式子,同时可以用t++在水平方向上扩大,通过这种方法成功降低了复杂度。具体的代码如下,有注释,大家应该都可以看得很明白:

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <assert.h>
  6 #include<stdlib.h>
  7 using namespace std;
  8 
  9 const int MAX = 10000;
 10 
 11 int num[MAX][MAX],sum[MAX][MAX];
 12 
 13 /*最大子数组之和*/  
 14 int MaxSubSum(int arr[],int nLen)  
 15 {  
 16     assert(num && nLen > 0);  
 17     int nMaxSum = arr[0];  
 18     int nCurSum = arr[0];  
 19     for (int i = 1;i < nLen;i++)  
 20     {  
 21         if (nCurSum < 0)  
 22         {  
 23             nCurSum = arr[i];  
 24         }  
 25         else  
 26         {  
 27             nCurSum += arr[i];  
 28         }  
 29         nMaxSum = max(nCurSum,nMaxSum);  
 30     }  
 31     return nMaxSum;  
 32 }  
 33 /*首尾相连最大子数组之和*/  
 34 
 35 int MaxSubSum_h(int arr[],int nLen)  
 36 {  
 37     assert(num && nLen > 0);  
 38     int nMaxSum = arr[0];  
 39     int nCurSum = arr[0];  
 40     for (int i = 1;i < nLen;i++)  
 41     {  
 42         if (nCurSum < 0)  
 43         {  
 44             nCurSum = arr[i];  
 45         }  
 46         else  
 47         {  
 48             nCurSum += arr[i];  
 49         }  
 50         nMaxSum = max(nCurSum,nMaxSum);  
 51     }  
 52     for (int i = 0;i < nLen;i++)  
 53     {  
 54         if (nCurSum < 0)  
 55         {  
 56             nCurSum = arr[i];  
 57         }  
 58         else  
 59         {  
 60             nCurSum += arr[i];  
 61         }  
 62         nMaxSum = max(nCurSum,nMaxSum);  
 63     }  
 64     return nMaxSum;  
 65 }  
 66 /*把原矩阵第i行和第j行之间元素进行压缩,形成一个一维数组*/
 67 void InitSumArr(int nXLen,int nYLen)
 68 {
 69     assert(num && *num && sum && *sum);
 70     assert(nXLen > 0 && nYLen > 0);
 71     for (int i = 0;i < nXLen;i++)//横坐标
 72     {
 73         for (int j = 0;j < nYLen;j++)//纵坐标
 74         {
 75             sum[i][j] = 0;
 76             for (int t = 0;t <= i;t++)
 77             {
 78                 sum[i][j] += num[t][j];
 79             }
 80         }
 81     }
 82 }
 83 /*枚举二维数组,压缩成一维数组,求解最大子数组和*/
 84 int MaxSubMatrixSum(int nXLen,int nYLen)
 85 {
 86     assert(num && *num && sum && *sum);
 87     assert(nXLen > 0 && nYLen > 0);
 88     int nMaxSum = -0x3f3f3f3f;
 89     int nCurSum = -0x3f3f3f3f;
 90     int temp[MAX];
 91     for (int i = 0;i < nXLen;i++)
 92     {
 93         for (int j = i;j < nXLen;j++)
 94         {
 95             if (i == 0)
 96             {
 97                 for (int t = 0;t < nYLen;t++)
 98                 {
 99                     temp[t] = sum[j][t];
100                 }
101                 nCurSum = MaxSubSum(temp,nYLen);
102                 nMaxSum = max(nCurSum,nMaxSum);
103             }
104             else
105             {
106                 //计算每列元素和,并求最大子数组之和
107                 for (int t = 0;t < nYLen;t++)
108                 {
109                     temp[t] = sum[j][t] - sum[i - 1][t];
110                 }
111                 nCurSum = MaxSubSum(temp,nYLen);
112                 nMaxSum = max(nCurSum,nMaxSum);
113             }
114         }
115     }
116     return nMaxSum;
117 }
118 
119 int main()
120 {
121     freopen("input.txt","r",stdin);
122     int nXLen = 0;
123     int nYLen = 0;
124     char c;
125     
126     cin>>nXLen>>c>>nYLen>>c;
127 
128     for (int i = 0;i < nXLen;i++)
129         for (int j = 0;j < nYLen;j++){
130             cin>>num[i][j];
131             if(j!=nYLen-1)   cin >> c;
132         }
133 
134     InitSumArr(nXLen,nYLen);
135     cout<<MaxSubMatrixSum(nXLen,nYLen)<<endl;
136     system("pause");
137     return 0;
138 }

     接下来是 水平垂直方向连接的问题,其实就是第一个问题的扩展,最重要的思路就是扩大空间,在水平或垂直方向上再补一个矩阵,同时保证j-i分别小于长宽,从而实现了连接,时间复杂度也没有上升,具体这部分的代码如下:(其他代码与第一个问题相同)

      _v

 1 int MaxSubMatrixSum_v(int nXLen,int nYLen)
 2 {
 3     assert(num && *num && sum && *sum);
 4     assert(nXLen > 0 && nYLen > 0);
 5     int nMaxSum = -0x3f3f3f3f;
 6     int nCurSum = -0x3f3f3f3f;
 7     int temp[MAX];
 8     for (int i = 0;i < nXLen;i++)
 9     {
10         for (int j = i;(j - i) < nXLen;j++)
11         {
12             if (i == 0)
13             {
14                 for (int t = 0;t < nYLen;t++)
15                 {
16                     temp[t] = sum[j % nXLen][t];
17                 }
18                 nCurSum = MaxSubSum(temp,nYLen);
19                 nMaxSum = max(nCurSum,nMaxSum);
20             }
21             else
22             {
23                 //计算每列元素和,并求最大子数组之和
24                 for (int t = 0;t < nYLen;t++)
25                 {
26                     temp[t] = sum[(j % nXLen)][t] - sum[i][t] + sum[nXLen - 1][t];
27                 }
28                 nCurSum = MaxSubSum(temp,nYLen);
29                 nMaxSum = max(nCurSum,nMaxSum);
30             }
31         }
32     }
33     return nMaxSum;
34 }

      _h(具体区别见MaxSubSum_h这个函数,有注释,实际思路是一样的)

 1 int MaxSubMatrixSum_h(int nXLen,int nYLen)
 2 {
 3     assert(num && *num && sum && *sum);
 4     assert(nXLen > 0 && nYLen > 0);
 5     int nMaxSum = -0x3f3f3f3f;
 6     //int Max = -0x3f3f3f3f;    
 7     int nCurSum = -0x3f3f3f3f;
 8     int temp[MAX];
 9     for (int i = 0;i < nXLen;i++)
10     {
11         for (int j = i;j < nXLen;j++)
12         {
13             if (i == 0)
14             {
15                 for (int t = 0;t < nYLen;t++)
16                 {
17                     temp[t] = sum[j][t];
18                 }
19                 nCurSum = MaxSubSum_h(temp,nYLen);
20                 nMaxSum = max(nCurSum,nMaxSum);
21             }
22             else
23             {
24                 //计算每列元素和,并求最大子数组之和
25                 for (int t = 0;t < nYLen;t++)
26                 {
27                     temp[t] = sum[j][t] - sum[i - 1][t];
28                 }
29                 nCurSum = MaxSubSum_h(temp,nYLen);
30                 nMaxSum = max(nCurSum,nMaxSum);
31             }
32         }
33         //Max = max(nCurSum,Max);
34     }
35     return nMaxSum;
36 

      这就是作业的基本思路,接下来我回答一下老师这次提到的问题。

      1、这次我是通过把相似但不同的问题单独模块化的方法来设计,这样具体的问题只要提取相应的模块即可,个人感觉比较稳定,当然没有很多很大的数据的考验。

      2、单元测试/代码覆盖率这个内容我还是很生疏,这次我没有涉及,我是用dev c++编译的,以后我会补上这个内容。

      3、第三个问题的填表情况如下:

 

 

Personal Software Process Stages

时间百分比(%)

实际花费的时间 (分钟)

原来估计的时间 (分钟)

Planning

计划

     

·         Estimate

·         估计这个任务需要多少时间,把工作细化并大致排序

 15%  1h  30mins

Development

开发

     

·         Analysis

·         需求分析 (包括学习新技术)

 10%  50mins  30mins

·         Design Spec

·         生成设计文档

     

·         Design Review

·         设计复审 (和同事审核设计文档)

     

·         Coding Standard

·         代码规范 (制定合适的规范)

     

·         Design

·         具体设计

 30%  2h30mins  2h

·         Coding

·         具体编码

 20%  1h30mins  2h

·         Code Review

·         代码复审

 5%  30mins  10mins

·         Test

·         测试(自我测试,修改代码,提交修改)

 20%  1h30mins  1h

Reporting

总结报告

     
  • Test Report
  • 测试报告
   

 

 
  • Size Measurement
  • 计算工作量
  • Postmortem & Improvement Plan
  • 事后总结, 并提出改进
       
         
Total 总计 100% 总用时   8h 总估计的用时    6h

     总结,这次实践,首先对我来说非常具有挑战性,是个很好的机会,既真实发现了自己的不足,也锻炼了能力;其次,我学会了把一个复杂的问题分解成几个小问题,循序渐进,我也理解了老师这次出题的良苦用心,还有,通过填写表格,我深刻体会到了科学开发的重要性,正确的开发方法可以使我们提高效率,缩短时间,我在这方面还需要学习的很多,最后,通过这次作业,激发了我学习算法和优化的热情。

      大致就这些,最后希望老师可以给我们讲解一下联通的问题,拓展我们的思路!