题目:返回一个整数数组中最大子数组的和
要求:(在原有代码上进行迭代)
1.输入一个整数数组,数组中有正数和负数。
2.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
3.如果数组a[0]……a[n-1]首尾相邻,允许a[i-1]……a[n-1]、a[0]……a[j-1]之和最大。
4.同时返回最大子数组的位置。
5.求所有子数组的和的最大值。
分析:
在本次编写的代码中使用了可变数组vector,它与一般数组作为函数参数不同,当vecto作为函数的参数时,在声明或定义函数时,vector数组名前要加引用符号&,如本次使用的函数:
void reverse(vector<LL> &a);如果少了&,求出的结果则会与预想中的结果有很大的不同
工作照:
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 using namespace std; 5 typedef long long LL; 6 #define MAX 1010 7 LL max(LL a, LL b) //求a和b的最大值 8 { 9 int h; 10 a >= b ? h = a : h = b; 11 return h; 12 } 13 LL maxsum(vector<LL> &a, int &index) //求可变数值a中的最大子数组之和 14 { 15 int dp[MAX]; 16 dp[0] = a[0]; 17 /* 18 *最大连续序列之和只有两种情况,分别是: 19 * 1.最大和的连续序列只有一个元素,即以array[i]开始,以array[i]结束,此时最大和就是array[i]本身 20 * 2.最大和的连续序列有多个元素,即从前面的某处的array[p]开始(p<i),一直到array[i]结尾 ,此时最大和为array[i]+dp[i-1]; 21 */ 22 for (int i = 1; i<a.size(); i++) 23 { 24 dp[i] = max(a[i], dp[i - 1] + a[i]); 25 } 26 int k = 0; 27 for (int i = 0; i<a.size(); i++) 28 { 29 if (dp[i]>dp[k]) 30 { 31 k = i; 32 } 33 } 34 index = k; 35 return dp[k]; //返回最大值 36 } 37 void reverse(vector<LL> &a)//使可变数组中的数值变为其相反数 38 { 39 for (int i = 0; i<a.size(); i++) 40 { 41 a[i] = -a[i]; 42 } 43 } 44 int index(vector<LL>&a, LL sum, int i)//求最大连续子数组开始的下标 45 { 46 while (sum) 47 { 48 sum -= a[i--]; 49 } 50 i++; 51 return i; 52 } 53 int main() 54 { 55 vector<LL> arrays; 56 LL n; 57 char flag = 48; 58 while (flag != 10 && flag != 13) 59 { 60 cin >> n; 61 flag = getchar(); 62 arrays.push_back(n); 63 } 64 int index1 = 0, index2 = 0; 65 /* 66 *最大连续子段有两种情况: 67 *1.正常数组中间的某一段和最大。 68 *2.此数组首尾相接的某一段和最大。这种情况是由于数组中间某段和为负值且绝对值很大导致的,此时可以先把原数组的和求出(记为ans), 69 * 再把原数组取反然后求其最大子数组之和(记为ans2),此时原数组最大字数之和就是ans+ans2 70 */ 71 int ans1 = maxsum(arrays, index1); 72 int index3 = index(arrays, ans1, index1); 73 int sum = 0; 74 for (int i = 0; i<arrays.size(); i++) 75 { 76 sum += arrays[i]; 77 } 78 reverse(arrays); 79 int ans2 = maxsum(arrays, index2); 80 int index4 = index(arrays, ans2, index2); 81 int ans = max(ans1, sum + ans2); 82 cout << "最大子数组之和为:" << ans << endl; 83 cout << "最大子数组为:"; 84 if (ans == ans1) 85 { 86 for (int i = index3; i != index1 + 1; i++) 87 { 88 cout << -arrays[i] << " "; 89 } 90 cout << endl; 91 } 92 else 93 { 94 for (int i = index2 + 1; i < arrays.size(); i++) 95 { 96 cout << -arrays[i] << " "; 97 } 98 for (int i = 0; i < index4; i++) 99 { 100 cout << -arrays[i] << " "; 101 } 102 } 103 system("pause"); 104 return 0; 105 }
运行截图:
周活动记录日志:
日期\任务 | 听课/时 | 编写程序/时 | 查阅资料/时 | 日总计/时 |
星期一 | 2 | 2 | 4 | |
星期二 | 2 | 2 | ||
星期三 | 2 | 2 | 4 | |
星期四 | 2 | 1 | 3 | |
星期五 | 4 | 4 | ||
星期六 | ||||
星期日 | 1 | 1 | ||
周总计 | 4 | 11 | 3 | 18 |
时间记录日志:
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间/分 | 活动 | 备注 |
3/21 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程上课 |
19:00 | 21:00 | 60 | 编写程序 | 课堂练习作业 | ||
3/22 | 19:00 | 21:30 | 20 | 120 | 自习 | |
3/23 | 14:30 | 18:00 | 15 | 自习 | ||
19:00 | 22::00 | 180 | 编写程序 | 作业 | ||
3/24 | 14:00 | 15:50 | 10 | 100 | 上课 | 软件工程上课 |
20:00 | 22:10 | 10 | 120 | 查资料,分析程序 | 课堂练习作业 | |
3/25 | 16:20 | 18:30 | 10 | 120 | 编程 | |
19:10 | 21:45 | 145 | 查阅资料+编程 |
缺陷日志:
日期 | 编号 | 缺陷内容 | 引入阶段 | 排除阶段 | 修复时间 | 修复缺陷 |
3月21日 | 1 | 如何来存储子 问题的最优解 | 编写代码 | 思考、查资料 | 80+ | 利用一维数组 来存储 |
3月25日 | 2 | 如何计算循环 数组首尾相接处 连续子段的和 | 编写代码 | 思考、查资料 | 120+ | 先求原数组的和, 再将原数组取反求 最大子数组之和, 最后将两者相加 |
团队成员:张绍佳、杜文星(博客:http://www.cnblogs.com/duwenxing/p/5322447.html)