1052 最大M子段和 DP

2022-04-11 02:02:15 字數 1606 閱讀 8520

1052 最大m子段和

基準時間限制:2 秒 空間限制:131072 kb 分值: 80 難度:5級演算法題

n個整數組成的序列a[1],a[2],a[3],…,a[n],將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m >= n個數中正數的個數,那麼輸出所有正數的和。

例如:-2 11 -4 13 -5 6 -2,分為2段,11 -4 13一段,6一段,和為26。

input

第1行:2個數n和m,中間用空格分隔。n為整數的個數,m為劃分為多少段。(2 <= n , m <= 5000)

第2 - n+1行:n個整數 (-10^9 <= a[i] <= 10^9)

output

輸出這個最大和
input示例

7 2

-211

-413-56

-2

output示例

26

//題意有點難懂,應該是說,從 n 個數中,選出小於等於 m 段,不相交,並且和最大

顯然dp題,但怎麼設計比較難,假設劃分成 x 段,對於每個元素,有這樣的考慮,

1、和上乙個連起來,就是上乙個位置分為 x 段

2、或者新開一段,就是上乙個位置分 x-1 段

那麼, dp[i][j] 表示前 i 個數選出 j 段,並且最後一段有 dat[i]

dp[i][j] = max(dp[i-1][j] , dp[j-1 -- i-1][j-1])

然後發現這是 n^3 ,得優化一下

dp[j-1 -- i-1][j-1] 這個可以用乙個陣列存一下,

設為 pre[i][j] ,表 前 i 個數,選出 j 段的最大和

pre[i][j] = max(pre[i-1][j],dp[i][j])

然後可以發現,最多和 j-1 有關,所以可以滾動一下優化空間,就可以愉快的dp辣

1 #include 2

using

namespace

std;

3#define mod 1000000007

4#define inf 0x3f3f3f3f

5#define eps 1e-9

6#define ll long long

7#define mx 500589

intn,k;

10int

dat[mx];

11 ll dp[mx][2

];12 ll pre[mx][2

];13

14int

main()

1525 ll ans =0;26

for (int j=1;j<=k;j++)

2733 ans = max(ans,pre[n][j&1

]);34

}35 printf("

%lld\n

",ans);36}

37return0;

38 }

view code

1052 最大M子段和 (dp)

n個整數組成的序列a 1 a 2 a 3 a n 將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m n個數中正數的個數,那麼輸出所有正數的和。例如 2 11 4 13 5 6 2,分為2段,11 4 13一段,6一段,和為26。input 第1行 2個數n和m,中間用空格分隔。...

51nod 1052 最大M子段和 DP

題目傳送門 好吧,好像是我zz了,原來連續的一段數可以當做許多段數來看的 突然掀桌,氣得我都變成簡筆畫了!害得我wa了6發!其實這題就是一道非常水的dp題,定義f i j 0 1 表示前 i 個數選了 j段,第三維表示當前的數是否被選在第 j 段數內。然後直接進行狀態轉移就行了。突然發現這樣開陣列會...

51Nod 1052 最大M子段和 DP

第一眼dp 第二眼隔板法 第三眼。嗯?第二眼好像看偏了?重新看第二眼 二維dp 所以說這道題是看兩眼就可以看出來做法的比較裸的dp題 wa了一發以後又重新看了一眼題面 嗯,要開long long 所以說這道題是看三眼就可以ac的比較裸的dp題 做完後倒回來看一眼自己的程式 嗯,只用到前面的一維 陣列...