NYOJ 742 (多段子串和)

2021-07-22 03:17:31 字數 1351 閱讀 1448

題目:給你乙個序列 s1, s2, s3, s4 ... sx, ... sn (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ sx ≤ 32767). 我們定義

sum(i, j) = si + ... + sj (1 ≤ i ≤ j ≤ n).現在給你乙個 m(8>m>0&&m

sum(i1, j1) + sum(i2, j2) + sum(i3, j3) + ... + sum(im, jm) ;我們規定他是不相交的。

請輸出m段最大和,比如:m = 2,n = 6 , 它的結果是 9;

要用到兩個dp;

dp[i][j]表示分成i段,最後一段以j結尾的最大子串和。

dp2[i][j]表示分成 i段,到第j個數字的最大字串和(分法不一定包括的j,注意和上面區分)

答案就是dp2[m][n];

轉移方程為dp[i][j] = max(dp[i][j - 1], dp2[i - 1][j  - 1]) + z[j];//兩種 情況,要麼是接在前乙個後面,要麼是單獨作為一段的開頭

dp2[i][j] = max(dp[i][j], dp2[i][j - 1]);//考慮最新的分法是否超過了最大值

考慮使用滾動陣列,dp的話只使用當前層的前乙個,所以完全沒有問題。dp2的話使用了當前層的前乙個和上一層的前乙個,所以我們在更新當前層的時候不能馬上覆蓋到上一層的,因為在下一層時要用到。所以考慮使用乙個變數來暫時儲存當前層;

轉移方程變為:dp[j] = max(dp[j - 1], dp2[j - 1]) + z[j];

dp2[j - 1] = ans;//上一層的用完才覆蓋

ans = max(dp[j], ans);//暫時不覆蓋當前層,下一層要用

#include #include #include #include #include #include #include using namespace std;

#define maxn 275005

#define mod 1000000

#define ll long long int

int t, n, m, x;

int z[1000005];

ll dp[1000005];

ll dp2[1000005];

ll ans;

int main()

memset(dp, 0, sizeof(dp));

memset(dp2, 0, sizeof(dp2));

dp[0] = dp2[0] = 0;

for (int i = 1; i <= m; ++i)

}printf("%lld\n", ans);

}}

NYOJ 742 最大m段和 區間DP

經典區間dp 最大m段和 最大連續和問題 是最大m段和問題的乙個特例,其實是當m 1的一種特殊情況。oj題目 include include define inf 0x3f3f3f3f using namespace std const int maxn 1000000 5 typedef long...

nyoj 子串和再續 742 (DP)

時間限制 1000 ms 記憶體限制 65535 kb 難度 4 描述 給你乙個序列 s1,s2,s3,s4 sx,sn 1 x n 1,000,000,32768 sx 32767 我們定義 sum i,j si sj 1 i j n 現在給你乙個 m 8 m 0 m 輸入 輸入 t,表示t組資料...

nyoj 44 子串和 最大子串和

常見的做法有 列舉區間 動態規劃等。昨天突然想到了乙個o n 的演算法,拿來分享給諸位 我們從後向前看這串數字 5 6 2 3 5 發現倒數第一位就是負數 5 毫無疑問,這個負數肯定不在我的最大子串和裡,因為我們捨去它並不會影響我們鏈結其它有價值的數,所以我們將它拋棄。繼續考察,這時我們遇到了3,我...