hdu 1024 Max Sum Plus Plus 小白都可以看得懂的解析
阿新 • • 發佈:2018-05-16
acm這道題弄了很久,網上的很多都看不懂,所以想要寫一個像我這種菜鳥都可以看得懂的解析。
題意是將一個長度為n的序列,分成m段不相交叉的子段,使得他們的和最大。
於是可以用dp[i][j]來表示在前j個數中,以num[j]結尾並分為i段的最大和。此時我們可以得出一個式子,dp[i][j]=max(dp[i-1][k]+a[j],dp[i][j-1]+a[j]) (i-1< k< j-1)。分別表示num[j]單獨成段和num[j]加入以num[j-1]結尾的一段。
現在舉一個例子,序列為-1,4,-2,3,-2,3。
現在可以結合圖標來理解式子的意思了,例如dp[2][4]=max(max(-1,4,2,) , 2)+num[4]=7
也就是說計算dp[i][j]只用到了2層的數據,上一層的數據我們只用到了其中的最大值,於是在求dp[j]時,我們可以用premax[]來記錄i~j的最大值,在下一層時使用。
為什麽i=n時,從第n位開始有值呢?因為這是每個數字自己單獨成一段的情況,是滿足分成n段的必要條件。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1000000; int num[maxn],premax[maxn],dp[maxn]; int main(){ int n,m,temp; while(~scanf("%d %d",&m,&n)){ for(int i=1;i<=n;i++) scanf("%d",&num[i]); memset(dp,0,sizeof(dp)); memset(premax,0,sizeof(premax)); for(int i=1;i<=m;i++){ temp=-1e9; for(int j=i;j<=n;j++){ dp[j]=max(premax[j-1],dp[j-1])+num[j]; premax[j-1]=temp;//temp存放的是i~j-1中的最大值 temp=max(temp,dp[j]); } } printf("%d\n",temp); } return 0; }
hdu 1024 Max Sum Plus Plus 小白都可以看得懂的解析