日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最大子序列和的详解

發布時間:2024/9/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最大子序列和的详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.問題

例:求數列的最大子段和。 給定n個元素的整數列(可以能為負整數),a1,a2,…,an。求數列的字段,使其和最大。

例如:當(a1, a2, a3, a4, a5, a6)=(-2, 11, -4, 13, -5, -2)時,最大子段和為sum(11-4+13)=20。

二.解決方法

我這里采用兩種方法:①遍歷的方法? ②分治法

①遍歷法

原理分析:遍歷該數組,每遍歷一個i元素就判斷temp+a[i]是否大于a[i],如果大于就更新temp=temp+a[i],否則temp=a[i],最后temp跟當前最大子序列和maxsum比較,如果大于,則maxsum=temp;否則不更新maxsum;最后遍歷完,直接返回maxsum.

遍歷法的c語言源碼:

#include<stdio.h> //類似于01背包問題 int start,end; int MaxSubsequenceSum( int A[], int n) {int tempsum = 0;int maxSum = 0;int tstart=0,tend=0;for (int j = 0;j < n;j++) //遍歷數組{ if((tempsum + A[j]) > A[j]){ //判斷臨時最大和+一個當前元素是否大于當前元素,如果大于,則把當前元素加進來,更新臨時最大和,否則臨時最大和更新為當前元素tempsum=tempsum + A[j];tend=j; //更新末尾位置 }else{ //如果臨時最大和+一個當前元素小于當前元素,則更新臨時最大和tempsum=A[j];tstart=j; //更新起始位置}if (tempsum > maxSum){ // 通過當前臨時最大和與上一個最大和作比較,如果大于則更新最大和maxSum = tempsum;start=tstart; //更新起始位置end=tend; //更新末尾位置}}return maxSum; } int main() {int maxSubSum,n,i;int a[101]; while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++)scanf("%d",&a[i]);maxSubSum = MaxSubsequenceSum(a, n);printf("%d %d %d\n",maxSubSum,start,end);}return 0; }

②分治法

原理分析:此問題用二分法分解后的兩個子序列(子問題)并不獨立,因為有可能最長的連續不升數列正好存在于兩個子序列的連接位置。 ? ?

?如果將所給的序列a[1..n]分為長度相等的2段a[1--(n/2)]和a[(n/2)+1--n],則a[1--n]的最長連續不升數列有3種情況:

1) a[1..n]的最長連續不升數列與a[1..(n/2)]的最長連續不升數列相同;

2) a[1..n]的最長連續不升數列與a[(n/2)+1..n]的最長連續不升數列相同;

3) a[1..n]的最長連續不升數列為∑a[k],且1≤i≤(n/2),(n/2),(n/2)+1≤j≤n。

情況1和情況2可分別遞歸求得。 對于情況3,如果不在情況1和情況2中,則a[(n/2)]與a[(n/2)+1]一定在最優子序列中。因此,我們可以計算出a[i..(n/2)]的最大值s1;并計算出a[(n/2)+1..j]中的最大值s2。則s1+s2即為出現情況3時的最優值。

c語言源碼:

#include<stdio.h> #define max 100 int start=0; int end=0; int minsum(int a[], int left, int right) {int s,s0, s1, lf, rt;if (left == right)return a[left];else {int mid = (left + right)/2;int leftsum = minsum(a, left, mid); //左子序列最大和int rightsum = minsum(a, mid + 1, right); //右子序列最大和s0 = 0; //左邊臨時和lf = 0;for(int i = mid; i >= 0; i--) {lf += a[i];if (lf > s0) { //加上當前的數如果大于左邊臨時和,則更新左邊臨時和s0 = lf;start = i; //起始點}}s1 = 0; //右邊臨時和rt = 0;for(i = mid + 1;i <= right; i++){rt += a[i];if (rt > s1) {s1 = rt;end = i; //末尾點}}s = s0 + s1;if (s< leftsum&&rightsum < leftsum)return leftsum;else if (s<rightsum&&rightsum>leftsum)return rightsum;else{return s;}} } int main() {int a[max],num,k=0,sum;while (scanf("%d", &num) != EOF) {k = 0;while (k<num){scanf("%d", &a[k]);k++;}sum = minsum(a, 0, num-1);printf("%d %d %d\n", sum,start,end);}return 0; }

?

總結

以上是生活随笔為你收集整理的最大子序列和的详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。