跟<算法导论(第三版)>上的一样,抄下来的
30 - 60 ms
标准的分治策略
1 #include <stdio.h> 2 3 int A[100000], Lenght; 4 const int NegativeInfinity = -1000000; 5 6 int gLow, gHigh, gSum; 7 8 void FindMaxCrossingSubArray(int low, int mid, int high) 9 { 10 int left_sum = NegativeInfinity; 11 int sum = 0; 12 int max_left = mid; 13 for (int i = mid; low <= i; i--) 14 { 15 sum += A[i]; 16 if (sum >= left_sum) 17 { 18 left_sum = sum; 19 max_left = i; 20 } 21 } 22 23 int right_sum = NegativeInfinity; 24 sum = 0; 25 int max_right = mid + 1; 26 for (int i = mid + 1; i <= high; i++) 27 { 28 sum = sum + A[i]; 29 if (sum > right_sum) 30 { 31 right_sum = sum; 32 max_right = i; 33 } 34 } 35 36 gLow = max_left; 37 gHigh = max_right; 38 gSum = left_sum + right_sum; 39 } 40 41 void FindMaxSubArray(int low, int high) 42 { 43 if (low == high) 44 { 45 gLow = low; 46 gHigh = high; 47 gSum = A[low]; 48 return; 49 } 50 51 int mid = (high + low) / 2; 52 FindMaxSubArray(low, mid); 53 int left_low = gLow, left_high = gHigh, left_sum = gSum; 54 55 FindMaxSubArray(mid + 1, high); 56 int right_low = gLow, right_high = gHigh, right_sum = gSum; 57 58 FindMaxCrossingSubArray(low, mid, high); 59 int cross_low = gLow, cross_high = gHigh, cross_sum = gSum; 60 61 if (left_sum >= right_sum && left_sum >= cross_sum) 62 { 63 gLow = left_low; 64 gHigh = left_high; 65 gSum = left_sum; 66 } 67 else if (cross_sum >= right_sum && cross_sum >= left_sum) 68 { 69 gLow = cross_low; 70 gHigh = cross_high; 71 gSum = cross_sum; 72 } 73 else 74 { 75 gLow = right_low; 76 gHigh = right_high; 77 gSum = right_sum; 78 } 79 } 80 81 int main() 82 { 83 int N; 84 scanf("%d", &N); 85 86 for (int index = 0; index < N; index++) 87 { 88 // input 89 int number; 90 scanf("%d", &number); 91 92 for (int i = 1; i <= number; i++) 93 { 94 scanf("%d", A + i); 95 } 96 97 // find 98 FindMaxSubArray(1, number); 99 100 // output 101 printf("Case %d: %d %d %d ", index + 1, gSum, gLow, gHigh); 102 103 if (index != N - 1) 104 printf(" "); 105 } 106 107 return 0; 108 }
网上大神的
来源: http://acm.hdu.edu.cn/discuss/problem/post/reply.php?postid=23376&messageid=1&deep=0
15 ms 的光景
关键是 最大子数组一定是在一个负号之前
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 5 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 6 7 int main(int argc, char *argv[]) { 8 int length; 9 int Num[100000]; 10 int nums,i,times=1; 11 int sum,pre_x,x,pre_y,y,max; 12 scanf("%d",&nums); 13 while(nums-->0){ 14 sum=0;max=0; 15 pre_x=0;pre_y=0;x=0;y=0; 16 scanf("%d",&length); 17 for(i=0; i<length; i++){ 18 scanf("%d",&Num[i]); 19 } 20 max=Num[0]; 21 for(i=0; i<length; i++){ 22 sum+=Num[i]; 23 24 if(Num[i]>0)y=i; 25 if(sum>max){ 26 pre_x=x; 27 pre_y=y; 28 max=sum; 29 } 30 if(sum<0){ 31 sum=0;x=i+1;y=i+1; 32 } 33 } 34 printf("Case %d: ",times); 35 printf("%d %d %d ",max,pre_x+1,pre_y+1); 36 if(nums>0)printf(" "); 37 times++; 38 } 39 return 0; 40 }