1. 程式人生 > >hdu-1024 Max Sum Plus Plus

hdu-1024 Max Sum Plus Plus

ati integer 最大連續 fun plus con begin 二維數組 and

Now I think you have got an AC in Ignatius.L‘s "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.

Given a consecutive number sequence S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ Sx ≤ 32767). We define a function sum(i, j) = S i
+ ... + S j (1 ≤ i ≤ j ≤ n).

Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed).

But I`m lazy, I don‘t want to write a special-judge module, so you don‘t have to output m pairs of i and j, just output the maximal summation of sum(i x
, j x)(1 ≤ x ≤ m) instead. ^_^

InputEach test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 ... S n.
Process to the end of file.
OutputOutput the maximal summation described above in one line.

1 3 1 2 3
2 6 -1 4 -2 3 -2 3

Sample Output

6
8


        
 

Hint

Huge input, scanf and dynamic programming is recommended.

這題好難啊,看了很久題解才看明白。 

題意:給定n個數,從中選m串不重合的子串,求m串最大的子串和。

解題思路:將問題分解為子問題,可從兩個角度出發:
從m的角度來看,當m等於1的時候,其實就是求最大連續子串和的題。
從n的角度來看,每個數字無非就兩種狀態, 一是在上個串;二是新串的起始。
這樣思路就出來了:
首先建立個dp[m][n]的數組。
假設m=1時,我們遍歷這n個數,每個數用dp數組記錄:
dp[1][i]=max(dp[1][i-1]+nu[i],0+nu[i])=max(dp[1][i-1],0)+nu[i];
這樣m=1時所有數的狀態就出來了。
那麽當m=2呢,無非在m=1的基礎上,看從哪裏截取,好讓最後的兩個串和最大。
但這裏又牽扯到一點,我們依然從上面兩個角度出發:
從m的角度來看,m=2時,要截取兩個串。兩個串的位置是不定的,只要不重合就行,也就是說,
如果要建第二個串,第一個串後面任何一個數都可以作為新串的開始,那該怎麽確定呢? 這就
要從n的角度來看,每個數兩種狀態,一是在上個串,二是新串的開始,如果這個數作為新串,
那它的上個串一定是這個數前面所有數中dp[1][2]最大的,如果不作為新串,還要加這個數的
話,就是直接dp[1][i]+nu[i];
m=3……n,以此類推,可得最後的狀態轉移方程是:
dp[i][j]=max(dp[i-1][j]+nu[i],max(dp[0][j-1]~dp[i-1][j-1])+nu[i]);
但因為這題又卡內存,所以用這個二維數組過不了。又因為其實每一層的數只和該數前面的上一
層的最大值有關,即只和max(dp[0][j-1]~dp[i-1][j-1])有關,所以用個記錄最大值的數
組mx[n]代替二維數組就行了。
即最終的轉移方程為:d[j]=max(d[j-1],pre[j-1])+num[j]; 附ac代碼:
技術分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int M = 1111111;
 6 const int inf = 0x3f3f3f3f;
 7 int nu[M],dp[M],mx[M];
 8 int main(){
 9     int n,m,maxx;
10     while(~scanf("%d %d",&m,&n)){
11         memset(dp,0,sizeof(dp));
12         memset(mx,0,sizeof(mx));
13         for(int i=1;i<=n;i++){
14             scanf("%d",&nu[i]);
15         }
16         for(int i=1;i<=m;i++){
17             maxx=-inf;
18             for(int j=i;j<=n;j++){
19                 dp[j]=max(dp[j-1]+nu[j],mx[j-1]+nu[j]);
20                 mx[j-1]=maxx;
21                 maxx=max(maxx,dp[j]);
22             }
23         }
24         printf("%d\n",maxx);
25     }
26     return 0;
27 }
View Code

 

hdu-1024 Max Sum Plus Plus