NKOI 3686 最大子段和

2021-07-12 01:45:32 字數 1334 閱讀 1431

p3686  最大子段和

時間限制 : 

- ms   

空間限制 : 

65536 kb

問題描述

給你乙個包含n個整數的序列,要求從中取出m個不相交的子段,要求這m個子段的和盡肯能大,輸出這個最大和。    

例如,n=7,m=2, 序列如下:    

-2  1  4   -2  3  -2  3

最優方案取出的兩段為    這兩段的和為9

輸入格式

第一行,兩個整數n和m

第二行,n個空格間隔的整數,表示整數數列

輸出格式

一行,乙個整數,表示所求答案

樣例輸入

7 2-2 1 4 -2 3 -2 3

樣例輸出9

提示1<=n <=100,000        1<=m<=300  且 m<=n   

數列中的數字範圍[-50000,50000]

我們可以發現這是一道動規,用f[i][j]表示前i個數分j段的最大和

我們再用sum做輸入陣列的字首和

那麼我們可以得到以下動規方程:

fi[j]=max(f[i-1][j],f[k][j-1]+sum[i]-sum[k])

即要麼放棄這個數(情況1),要麼將第k+1到第i個分成一段(情況2),轉移方程就完成了

然後我們想,f[i][j]要開到f[100005][305]大概120m,無法滿足題目的要求,因此我們應該使用滾動陣列

我們發現f[i][j]只與j和j-1有關,所以我們在使用陣列的時候只用討論j%2的情況即可

但是由於資料範圍較大,根據上面的動規方程我們要進行三次迴圈,所以需要優化演算法效率

在討論f[k][j-1]+sum[i]-sum[k]時,由於i相對於k是乙個常數,所以我們可以用乙個best[j]陣列記錄在討論將i個數分成j段時情況2的最大和,從而消掉k的迴圈

後來發現當輸入的資料都為負數時,由於演算法的不完美性,得出了錯誤答案,因此總結得出若輸入的全是負數,則輸出最大的m個數的和

#include#include#includeusing namespace std;

const int inf=2e9;

int a[100005],f[100005][2],sum[100005],best[305];

bool cmp(int a,int b)

int main()

if(flag){

int sum=0;

sort(a+1,a+1+n,cmp);

for(i=1;i<=m;i++)sum+=a[i];

cout<

例題 動規 NKOJ 3686 最大子段和

nkoj 3686 最大子段和 時間限制 ms 空間限制 65536 kb 問題描述 給你乙個包含n個整數的序列,要求從中取出m個不相交的子段,要求這m個子段的和盡肯能大,輸出這個最大和。例如,n 7,m 2,序列如下 2 1 4 2 3 2 3 最優方案取出的兩段為 這兩段的和為9 輸入格式 第一...

最大子段和

設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個...