代码改变世界

杭电ACMstep 3.2.1

2013-11-30 12:49  凝月流风  阅读(212)  评论(0编辑  收藏  举报

   题目是最大子序列和问题,跟以往的不同是和可以是负数,所以只需要改一下求最大子序列和的代码即可,依然是O(n)的时间复杂度

   思路是从左向右不断地找出每一个有可能成为最大和的子序列,用submax保存,每一次将它与Max进行比较更新Max

   submax的寻找方法是当前面序列a[i] ~a[j] 段的submax为负数时,将前面这段抛弃,另起炉灶,使submax = a[j+1],因为前面的负数部分只会

   使submax减小,所以将其抛弃(需要注意的是题目可能有多种情况,找出第一种,所以submax=0时还得保留)

 

  另外编程珠玑上面讲这个问题的几种解决方式讲的很详细,递归虽然要O(n*logn)的复杂度,但觉得还是特别赞的方法

  代码如下:

  

//最大子序列和变形 
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
  int N, T, i, k = 0, a[100010];
  int Max, submax;
  bool flag = 0;
  cin >> T;
  while (k++ < T) {
      cin >> N;
      if (flag) cout << endl;
      submax = Max = -100000;  //初始化为负无穷 
      int s, t, s1;
        for (i = 0; i < N; i++) {
        cin >> a[i];
        //找出子串 
        if (submax < 0) {
              s1 = i;
            submax = a[i];
            } else {
              submax += a[i];
            }
            //更新Max 
            if (submax > Max) {
              s = s1; t = i;
              Max = submax;
            }
    }
    cout << "Case " << k << ":" << endl
         << Max << " " << s+1 << " " << t+1 << endl; 
    flag = 1;
    }
    return 0;
}