1. 程式人生 > 其它 >sdut3664順序表應用7:最大子段和之分治遞迴法

sdut3664順序表應用7:最大子段和之分治遞迴法

Description

給定n(1<=n<=50000)個整數(可能為負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整數均為負數時定義子段和為0,依此定義,所求的最優值為: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,當(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)時,最大子段和為20。

注意:本題目要求用分治遞迴法求解,除了需要輸出最大子段和的值之外,還需要輸出求得該結果所需的遞迴呼叫總次數。

遞迴呼叫總次數的獲得,可以參考以下求菲波那切數列的程式碼段中全域性變數count的用法:

#include
int count=0;
int main()
{
int n,m;
int fib(int n);
scanf("%d",&n);
m=fib(n);
printf("%d %d\n",m,count);
return 0;
}
int fib(int n)
{
int s;
count++;
if((n==1)||(n==0)) return 1;
else s=fib(n-1)+fib(n-2);
return s;
}

Input

第一行輸入整數n(1<=n<=50000),表示整數序列中的資料元素個數;

第二行依次輸入n個整數,對應順序表中存放的每個資料元素值。

Output

一行輸出兩個整數,之間以空格間隔輸出:

第一個整數為所求的最大子段和;

第二個整數為用分治遞迴法求解最大子段和時,遞迴函式被呼叫的總次數。

Sample

Input 

6
-2 11 -4 13 -5 -2

Output 

20 11

Hint

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int num;
 5 
 6 int max(int x, int y)
 7 {
 8     if(x<y) return y;
 9     else return x;
10 }
11 
12 int fenzhi(int a[], int left, int
right) 13 { 14 num++; 15 if(left>right) return 0; 16 if(left==right) return max(a[left], 0); 17 int suml, sumr, sum, re, rel, rer, i; 18 int mid = (left+right)/2; 19 rel = fenzhi(a, left, mid); ///單純從最大欄位和來講mid-1也可,不過根據題目給出的樣例中的次數來看應當是mid 20 rer = fenzhi(a, mid+1, right); 21 suml = 0; 22 sum = 0; 23 for(i=mid-1;i>=left;i--) 24 { 25 sum+=a[i]; 26 suml = max(suml, sum); 27 } 28 sumr = 0; 29 sum = 0; 30 for(i=mid+1;i<=right;i++) 31 { 32 sum+=a[i]; 33 sumr = max(sumr, sum); 34 } 35 sum = suml + sumr + a[mid]; 36 re = max(max(rel, rer), sum); 37 return re; 38 } 39 40 41 int main() 42 { 43 int n, i; 44 int a[50005]; 45 scanf("%d", &n); 46 for(i=0;i<n;i++) 47 { 48 scanf("%d", &a[i]); 49 } 50 num = 0; 51 int re = fenzhi(a, 0, n-1); 52 printf("%d %d\n", re, num); 53 return 0; 54 }