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