1. 程式人生 > >1024 Max Sum Plus Plus(DP + 滾動陣列)

1024 Max Sum Plus Plus(DP + 滾動陣列)

題目大意:求m個不相交區間的最大和

解題思路:這題是參考別人的,傳送門

再自己組織一下,用dp[i][j]表示前j個數組組成了i個不相交區間的最大和,其中第j個數字一定在某個區間內
那現在要決策的是,第j個數組是在和別的陣列成了一個區間,還是自己獨立成了一個區間
1.如果是在和別的陣列成了區間,那麼dp[i][j] = dp[i][j - 1] + num[j]
2.如果是獨立的區間,那麼dp[i][j] = dp[i - 1][k] + num[j]
其中的dp[i-1][k] = max(dp[i-1][i - 2], dp[i-1][i - 1] … dp[i-1][j-1])

綜上所述,dp[i][j] = max(dp[i][j - 1], dp[i - 1][k]) + num[j]
其中dp[i-1][k]可以用一個變數紀錄下來,紀錄所求的每個dp[i-1][k]的最大值
因為每個dp只和上一個有關,所以就可以化成滾動陣列求解了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
const int INF = 0x7fffffff;

int n, m;
int dp[N][2
], num[N], mmax[N]; void solve() { for (int i = 1; i <= n; i++) { scanf("%d", &num[i]); dp[i][0] = dp[i][1] = 0; } dp[0][0] = dp[0][1] = 0; int Max; for (int i = 1; i <= m; i++) { Max = -INF; for (int j = i; j <= n; j++) { dp[j][0
] = max(dp[j - 1][0] + num[j], dp[j - 1][1] + num[j]); dp[j - 1][1] = Max; Max = max(Max, dp[j][0]); } } printf("%d\n", Max); } int main() { while (scanf("%d%d", &m, &n) != EOF) solve(); return 0; }