homework-02
2013-10-01 12:48
141 查看
这是我第二次写博客,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++在水平方向上扩大,通过这种方法成功降低了复杂度。具体的代码如下,有注释,大家应该都可以看得很明白:
接下来是 水平垂直方向连接的问题,其实就是第一个问题的扩展,最重要的思路就是扩大空间,在水平或垂直方向上再补一个矩阵,同时保证j-i分别小于长宽,从而实现了连接,时间复杂度也没有上升,具体这部分的代码如下:(其他代码与第一个问题相同)
_v
_h(具体区别见MaxSubSum_h这个函数,有注释,实际思路是一样的)
这就是作业的基本思路,接下来我回答一下老师这次提到的问题。
1、这次我是通过把相似但不同的问题单独模块化的方法来设计,这样具体的问题只要提取相应的模块即可,个人感觉比较稳定,当然没有很多很大的数据的考验。
2、单元测试/代码覆盖率这个内容我还是很生疏,这次我没有涉及,我是用dev c++编译的,以后我会补上这个内容。
3、第三个问题的填表情况如下:
总结,这次实践,首先对我来说非常具有挑战性,是个很好的机会,既真实发现了自己的不足,也锻炼了能力;其次,我学会了把一个复杂的问题分解成几个小问题,循序渐进,我也理解了老师这次出题的良苦用心,还有,通过填写表格,我深刻体会到了科学开发的重要性,正确的开发方法可以使我们提高效率,缩短时间,我在这方面还需要学习的很多,最后,通过这次作业,激发了我学习算法和优化的热情。
大致就这些,最后希望老师可以给我们讲解一下联通的问题,拓展我们的思路!
言归正传,我来说说这次作业的思路,这次我的编写语言是c++,首先是二维数组求最大子数组的和的问题,参考作业一,可以想到把二维数组向一维的方向前进,最朴素的算法时间复杂度是O(n^6),不断优化,可以最终达到O(n^3),基本思路就是创建一个新的二维数组sum[i][t],其中每个元素代表从num[0][0]到num[i][j]所组成的矩阵中所有元素的和,这样在求任意一个矩阵就可以充分利用sum[j][t]-sum[i-1][t]这个式子,同时可以用t++在水平方向上扩大,通过这种方法成功降低了复杂度。具体的代码如下,有注释,大家应该都可以看得很明白:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <assert.h> #include<stdlib.h> using namespace std; const int MAX = 10000; int num[MAX][MAX],sum[MAX][MAX]; /*最大子数组之和*/ int MaxSubSum(int arr[],int nLen) { assert(num && nLen > 0); int nMaxSum = arr[0]; int nCurSum = arr[0]; for (int i = 1;i < nLen;i++) { if (nCurSum < 0) { nCurSum = arr[i]; } else { nCurSum += arr[i]; } nMaxSum = max(nCurSum,nMaxSum); } return nMaxSum; } /*首尾相连最大子数组之和*/ int MaxSubSum_h(int arr[],int nLen) { assert(num && nLen > 0); int nMaxSum = arr[0]; int nCurSum = arr[0]; for (int i = 1;i < nLen;i++) { if (nCurSum < 0) { nCurSum = arr[i]; } else { nCurSum += arr[i]; } nMaxSum = max(nCurSum,nMaxSum); } for (int i = 0;i < nLen;i++) { if (nCurSum < 0) { nCurSum = arr[i]; } else { nCurSum += arr[i]; } nMaxSum = max(nCurSum,nMaxSum); } return nMaxSum; } /*把原矩阵第i行和第j行之间元素进行压缩,形成一个一维数组*/ void InitSumArr(int nXLen,int nYLen) { assert(num && *num && sum && *sum); assert(nXLen > 0 && nYLen > 0); for (int i = 0;i < nXLen;i++)//横坐标 { for (int j = 0;j < nYLen;j++)//纵坐标 { sum[i][j] = 0; for (int t = 0;t <= i;t++) { sum[i][j] += num[t][j]; } } } } /*枚举二维数组,压缩成一维数组,求解最大子数组和*/ int MaxSubMatrixSum(int nXLen,int nYLen) { assert(num && *num && sum && *sum); assert(nXLen > 0 && nYLen > 0); int nMaxSum = -0x3f3f3f3f; int nCurSum = -0x3f3f3f3f; int temp[MAX]; for (int i = 0;i < nXLen;i++) { for (int j = i;j < nXLen;j++) { if (i == 0) { for (int t = 0;t < nYLen;t++) { temp[t] = sum[j][t]; } nCurSum = MaxSubSum(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } else { //计算每列元素和,并求最大子数组之和 for (int t = 0;t < nYLen;t++) { temp[t] = sum[j][t] - sum[i - 1][t]; } nCurSum = MaxSubSum(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } } } return nMaxSum; } int main() { freopen("input.txt","r",stdin); int nXLen = 0; int nYLen = 0; char c; cin>>nXLen>>c>>nYLen>>c; for (int i = 0;i < nXLen;i++) for (int j = 0;j < nYLen;j++){ cin>>num[i][j]; if(j!=nYLen-1) cin >> c; } InitSumArr(nXLen,nYLen); cout<<MaxSubMatrixSum(nXLen,nYLen)<<endl; system("pause"); return 0; }
接下来是 水平垂直方向连接的问题,其实就是第一个问题的扩展,最重要的思路就是扩大空间,在水平或垂直方向上再补一个矩阵,同时保证j-i分别小于长宽,从而实现了连接,时间复杂度也没有上升,具体这部分的代码如下:(其他代码与第一个问题相同)
_v
int MaxSubMatrixSum_v(int nXLen,int nYLen) { assert(num && *num && sum && *sum); assert(nXLen > 0 && nYLen > 0); int nMaxSum = -0x3f3f3f3f; int nCurSum = -0x3f3f3f3f; int temp[MAX]; for (int i = 0;i < nXLen;i++) { for (int j = i;(j - i) < nXLen;j++) { if (i == 0) { for (int t = 0;t < nYLen;t++) { temp[t] = sum[j % nXLen][t]; } nCurSum = MaxSubSum(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } else { //计算每列元素和,并求最大子数组之和 for (int t = 0;t < nYLen;t++) { temp[t] = sum[(j % nXLen)][t] - sum[i][t] + sum[nXLen - 1][t]; } nCurSum = MaxSubSum(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } } } return nMaxSum; }
_h(具体区别见MaxSubSum_h这个函数,有注释,实际思路是一样的)
int MaxSubMatrixSum_h(int nXLen,int nYLen) { assert(num && *num && sum && *sum); assert(nXLen > 0 && nYLen > 0); int nMaxSum = -0x3f3f3f3f; //int Max = -0x3f3f3f3f; int nCurSum = -0x3f3f3f3f; int temp[MAX]; for (int i = 0;i < nXLen;i++) { for (int j = i;j < nXLen;j++) { if (i == 0) { for (int t = 0;t < nYLen;t++) { temp[t] = sum[j][t]; } nCurSum = MaxSubSum_h(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } else { //计算每列元素和,并求最大子数组之和 for (int t = 0;t < nYLen;t++) { temp[t] = sum[j][t] - sum[i - 1][t]; } nCurSum = MaxSubSum_h(temp,nYLen); nMaxSum = max(nCurSum,nMaxSum); } } //Max = max(nCurSum,Max); } return nMaxSum;
这就是作业的基本思路,接下来我回答一下老师这次提到的问题。
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 |
大致就这些,最后希望老师可以给我们讲解一下联通的问题,拓展我们的思路!
相关文章推荐
- 第二次作业(homework-02)成绩公布
- homework-02
- homework-02 二维的,好喝的(二维数组的各种子数组)
- 最大二位子数组和问题(homework-02)
- homework-02 "最大子数组之和"的问题进阶
- homework-02
- homework-02 最大子区域和
- Strings and Regular Expressions(homework for 02)
- homework-02
- homework_02
- 最大连续子数组问题2-homework-02
- [课程相关]homework-02
- homework-02
- homework-02
- homework-02
- 现代程序设计 homework-02
- homework-02
- homework-02
- homework-02
- homework-02