問題: 給定n個整數(可能為負數)組成的序列a[1],a[2],a[3],…,a[n],求該序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。當所給的整均為
負數時定義子段和為0,依此定義,所求的最優值為: max,1<=i<=j<=n 例如,當(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)時,最大子段和為20。
1、最大子段和問題的簡單演算法
首先介紹的演算法是大家最容易想到的演算法 暴力求解 三層迴圈 第一層迴圈便是開頭元素 第二層迴圈表示結尾元素 第三層迴圈求開頭和結尾元素間值的和
**如下:
int maxsum(int n,int a,int &left,int &right)
} }
return sum;
2、第二種演算法是在第一種演算法的基礎上進行改進的 結果是將第三層迴圈給省略掉了 我們知道開頭和結尾其實並不需要每次都要重新將元素從開頭加到結尾 我們只需要從開頭開始 每加乙個元素都和之前求得的最大值比較 如果加上這個元素之後的和大於之前的最大值 那就更新最大值、開頭和結尾元素的下標
**如下:
int maxsum(int n,int a,int &left,int &right)
} }
return sum;
}
3、我們往往希望能夠找到解決問題更快得方法 無論是三層迴圈還是兩層迴圈 在大資料得情況下 都顯得很吃力 所以第三種給出動態規劃演算法
動態規劃演算法和第二種演算法有一點點的相同的地方就是每次得到的值都和之前的最大值進行比較 大於就更新 它的不同在於 只需要一層迴圈 具體思想是:從序列的第乙個元素(開頭)開始加起 當和不小於零時我們就有可能在加上下乙個元素之後得到的和比之前的和都要大 但是當我們加上乙個元素之後 和小於零了 那麼這個子串行就到此為止了 因為就算它在加上後面的乙個值之後大於原先的最大值那麼它也不是最大子段和了(乙個正數加上乙個負數是要變小的嘛) 那麼我們就從這個元素的下乙個元素(新的開頭)開始往後加重新找 依次類推 便可找到最大子段和的值
**如下:
int maxsum(int n,int a)
} return sum;
}
關於動態規劃的演算法 我們該怎麼輸入這個最大子段和呢 其實很簡單 我們只需要記住最大子段和的末尾元素的下標 然後依次往回減便可得到開頭元素 下面兩個簡單的例子:
hdu1003
ac**:
#include int main ()
else
if (dp[i]>max)
}
__int64 c=0;
left=right;
for (int i=right;i>=0;i--)
}
printf ("case %d:\n",count+1);
printf ("%i64d %d %d\n",max,left+1,right+1);
count++;
} return 0;
}
hdu1231
ac**:
#include #include int num[10010];
int main ()
} if (!flag)
else
if (b>sum)
}
int x=sum;
for (int i=right;i>=0;i--)
} printf ("%d %d %d\n",x,num[left],num[right]);
} }
return 0;
}
最大子段和
設a 是n個整數的序列,稱為該序列的子串行,其中1 i j n.子串行的元素之和稱為a的子段和.例如,a 2,11,4,13,5,2 那麼它的子段和是 長度為1的子段和 2,11,4,13,5,2 長度為2的子段和 9,7,9,8,7 長度為3的子段和 5,20,4,6 長度為4的子段和 18,15...
最大子段和
問題表述 n個數 可能是負數 組成的序列a1,a2,an.求該序列 例如 序列 2,11,4,13,5,2 最大子段和 11 4 13 20。1 窮舉演算法 o n3 o n2 2 分治法 將序列a 1 n 從n 2處截成兩段 a 1 n 2 a n 2 1 n 例項 三 最大子段和 問題表述 n個...
最大子段和
再給頂的n個數的陣列中選出連續的若干個數,使得他們的和是最大的,即最大連續自序列和.列如.序列.1 2 3 1 6 5 9 結果 當取子串行 3,1,6,5,9 結果12 我的思路.1.最大連續子串行的開頭是在1.n之中.的最大連續和 2.求出以i,開頭的最大連續和,此時開頭已經確定了,那麼通過列舉...