HDU1024 動態規劃 滾動陣列

2021-09-29 11:25:46 字數 1455 閱讀 2344

題目大意:把乙個陣列劃分成不相交的m段,使得這m段之和加起來最大。輸出最大值。

這道題從題意的分析可知要使用動態規劃來做

使用arr[j]來存放第j個數

dp[i][j]的含義:在包含arr[j]的前提下,前i段的最大值,那麼我們可以分以下兩種情況:

解釋一下為什麼第二種情況要使用max(dp[i-1][k])+arr[j], i-1<=k<=j-1,首先,我們要知道dp[i][j]是表示在包含arr[j]的前提下,前i段的最大值,但是呢,如果arr[j]是負數,那麼dp[i][j]肯定就不是表示前i段的最大和了,而前i段的最大和肯定是在之前出現的,同理dp[i-1][j-1]並不一定表示的前i-1段的最大和,但是前i-1段的最大和肯定是在i-1到j-1之間存在的,所以要使用dp[i-1][k], i-1<=k<=j-1

接下來我們就可以寫出遞推公式:

dp[i][j] = max(dp[i][j-1]+arr[j],max(dp[i-1][k])+arr[j]) i-1<=k<=j-1

但是上述的公式還有乙個漏洞 也就是dp[m][n],dp[m][n]這個表示的時在包含arr[n]的前提下的最大值,但是我們前面分析過,包含arr[n]的不一定是最大的,所以說最後還要用一次max(dp[m][k]) m<=k<=n

上述的公式看起來已經能夠解決這個問題了,但是其實還是不能解決,為什麼? 由於題目中的m的範圍並沒有給出,而n的範圍時1e6,所以按照上述方法做,最終肯定會爆記憶體

下面我們就採用滾動陣列來進行空間優化:

首先我們來分析以下遞推公式,遞推公式中的dp[i-1][k] i-1<=k<=j-1,表示的是前面狀態的最大和,而同時我們也不關心最大和到底是在哪乙個位置取,那麼我們就可以用pre[j-1]來表示前j-1個狀態的最大和,此時遞推公式就變成:

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

我們會發現此時遞推公式中只存在i了,那麼此時我們就可以將i去除

最終的遞推公式為:

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

下面為ac**:

#include

#include

#include

using namespace std;

const

int maxn =

1e6+5;

int n,m;

int dp[maxn]

;int pre[maxn]

;int arr[maxn]

;int

main()

}printf

("%d\n"

,maxnum);}

return0;

}

hdu 1024 滾動陣列優化

本題的大致意思為給定乙個陣列,求其分成 m個不相交子段和最大值的問題。解題思路 dp i j 表示前j個數分成i組,且j在第i組裡的最大值。dp i j max,前乙個表示j與j 1在i組裡,後乙個表示j單獨成組。但這道題的n很大,空間複雜度太高,所以要用滾動陣列。max dp i 1 k 就是上一...

HDU 1024 簡單dp 滾動陣列

要求 n個正數組成的序列,整數範圍 32768 s 32767,1 n 1,000,000,挑出m個無交集的連續子串行使這些序列和最大,並輸出最大值。方法 二維dp 滾動陣列降維。1.dp i j 表示第乙個數到下標為j的數挑出i個連續子串行組成的最大值。2.dp i j max dp i j 1 ...

hdu 1024(滾動陣列的學習)

學習了一下滾動陣列,dp中經常卡記憶體,而利用滾動陣列可以大大節省記憶體空間,不錯哦。1 include2 include3 include4 const int n 1000010 5 const int inf 1000000000 6 using namespace std 78 inta n...