Maximum sub-segments and description
Given a sequence of n (1<n<100) integers (containing negative integers) a1,a2,..., An, select the adjacent section of ai,ai+1,... AJ (1≤i≤j≤n) in this n number, and output the maximum value of the sequence sub-segment and maximum.
Input
Enter more than one set of test cases
Each set of test cases consists of 2 rows, one integer n for the first row, and then the second row has n integers
If the integer n is 0, the input ends
Output
Outputs the maximum value of the sequence sub-segment and
Sample Input
81-3 7 8-4) 12-10 60
Sample Output
23
Problem Analysis and Solution
/* Front Code */
#include <iostream>
#include <cstdio>using namespace Std;const int maxn = 1005;int A[MAXN], _max[maxn];/* join work Code eg:work () *//* post code */i NT Main () { //freopen ("In.txt", "R", stdin); while (Cin>>n, N) { for (int i = 1; I <= n; i + +) { cin>>a[i];//the entire process for ease of operation, the following table of our array starts with "1". } Work (); or work (1,n); cout<<m<<endl; } return 0;}
We can easily think of a brute force method that uses three loops to nest. (O (n^3))
1. Violence law void work () {for (int i = 1, i <= N; i++) {for (int j = i; J <= N; j + +) { int curm = 0;//Save the current and. for (int k = i; k <= J; k++) { Curm + = a[k]; if (Curm > m) { m = Curm; } } }}
It is found that there are a lot of repeated computations in the violence law, which can be optimized. (O (n^2))
2. Optimize code void Work () {for (int i = 1; I <= n; i++) { int curm = 0; for (int j = i; J <= N; j + +) { Curm + = a[j]; if (Curm > m) { m = Curm; } } }
The efficiency of optimization is not very high, we can consider the division of the law. (O (Nlog (n)))
Divide a[1n] into two parts of A[1N/2] and a[n/2+1n, which will produce three cases
(1) Maximum sub-segments of a[1n] and the largest sub-segments and the same as A[1N/2]
(2) Maximum sub-segments of a[1n] and the largest sub-segments and the same as a[n/2n]
(3) Maximum sub-segments of a[1n] and for Ai++aj,1<=i<=n/2,n/2+1<=j<=n
Our aim is to find out the largest of the three cases mentioned above.
3. Divide and conquer law
int work (int l, int r)//l:left r:right{ if (l = = r) m = a[l];//> 0? a[l]: 0; else { int c = (L + r)/2;//c:center int lm = Work (l,c),//lm:left sum int rm = Work (C+1,R);//rm:right sum int CLM = 0;//center ' s left sum int tlm = 0;//temp left sum for (int i = c; I >= l; i--) { TLM + = A[i]; if (TLM > CLM) clm = TLM; } int CRM = 0;//center ' s right sum int TRM = 0;//temp right sum for (int i = c + 1; I <= R; i++) { TRM + = A[i]; if (TRM > CRM) CRM = TRM; } int cm = CLM + crm;//center sum m = cm < LM? (RM < LM LM:RM): (CM < RM rm:cm); } return m;}
Although the code above is much better than brute force, the time wasted in allocating storage space for recursive calls is sometimes not negligible.
We introduce a more efficient algorithm-dynamic programming (O (n)), as follows:
A[0...I], which contains the maximum _max[i of a[i], and
(1) _max[i] = S[i-1]+a[i], s[i-1] > 0,
(2) _max[i] = A[i], s[i-1] <= 0;
Our goal is to ask Max (_max)
4. Dynamic planning void Work () { m =a[1]; _MAX[1] = a[1]; for (int i = 2; I <=n; i++) { _max[i] = _max[i-1] > 0 _max[i-1] + a[i]: a[i]; if (M < _max[i]) m = _max[i];} }
Maximum sub-segments and