码迷,mamicode.com
首页 > 编程语言 > 详细

最大子数组之和(2)

时间:2016-03-26 12:30:35      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

题目要求(在原有题目基础上):

  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+

先求原数组的和,

再将原数组取反求

最大子数组之和,

最后将两者相加

最大子数组之和(2)

标签:

原文地址:http://www.cnblogs.com/duwenxing/p/5322447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!