1. 程式人生 > >某種數列

某種數列

問題 找到 nbsp ostream max out for ali 由於

某種數列問題 (jx.cpp/c/pas) 1000MS 256MB

眾所周知,chenzeyu97有無數的妹子(阿掉!>_<),而且他還有很多惡趣味的問題,繼上次糾結於一排妹子的排法以後,今天他有非(chi)常(bao)認(cheng)真(zhe)去研究一個奇怪的問題。有一堆他的妹子站成一排,然後對於每個妹子有一個美麗度,當然美麗度越大越好,chenzeyu97妹子很多,但是質量上不容樂觀,經常出現很多美麗度為負數的妹子(喜聞樂見),chenzeyu97希望從一排妹子裏找出3隊連續的妹子,使她們的美麗度和最大。註意,一個妹子不能被編入多個隊伍而且一定要拿出三隊,不然czy會閑著沒事做~。

簡單滴說就是:

給定一個數列,從中找到3個無交集的連續子數列使其和最大。

【輸入文件】

第一行一個數n,表示數列長度。

接下來有n行,每行一個數,第i行為第i個數。

【輸出文件】

僅有一個數,表示最大和。

【樣例輸入】 jx.in

10

-1

2

3

-4

0

1

-6

-1

1

-2

【樣例輸出】 jx.out

7

【樣例說明】

第一隊妹子取2,3。

第二隊妹子取0,1。

第三隊妹子取1。

【數據範圍】

請大家放心,雖然chenzeyu97妹子無數,但是這次他叫來的個數n是有限的。=v=

對於30%的數據,妹子數不大於200。

對於60%的數據,妹子數不大於2000。

對於100%的數據,妹子數1000000。

而且,由於chenzeyu97沒有CCR那樣的影響力,所以他的妹子選完的最大美麗度和不超過maxlongint。(註:CCR隨便選就爆long long,因為他是把妹狂魔=V=)。

很明顯這是一道動歸題目,對於每個點有三種狀態,一種是與前面的組成一組,一種是不選,一種是與後面的組成一組,

如果與前面組成一組,那麽當前點就會成為前面那組的最後一個點,如果與後面組成一組,那麽前面的點就會組成當前

需要組數-1個組,然後當前點成為後面一組的起始點,如果不選的話,那麽到達當前點的狀態與前一個點的狀態是相同的,

似乎可以用一個二維數組進行轉移。但是,我們考慮,如果用一個二維數組,就無法考慮當前點不選的情況,所以需要一個

三維數組(相當於兩個二維數組),f[i][j][1]表示前i個組成j組,選第i個的情況,f[i][j][0]表示前i個組成j組不選第i個的情況。

那麽狀態轉移方程為

f[i][j][0]=f[i-1][j-1]

f[i][j][1]=max(max(f[i-1][j-1][0]+a[i],f[i-1][j-1][1]+a[i]),f[i-1][j][1]+a[i])

第一個很好理解,當前點如果不選的話,那麽當前點和前一個點狀態相同。

第二個的兩個max我們可以分開理解,裏面的max是為了找出當前點重新開始一組的情況,因為如果

當前點重新開始,前一個點不管是選還是不選都可以轉移。而外面的max是為了在當前點重新開始

一組還是繼續上一組進行抉擇。

最後輸出將n個分為3組最後一個選或不選中更優的那個即可。

附上代碼

 1 #include<cstdio>
 2 #include<Iostream>
 3 using namespace std;
 4 int n,a[1000010],f[1000010][4][2];
 5 int main()
 6 {
 7 
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;++i)
10     {
11         scanf("%d",&a[i]);
12     }
13     for(int i=1;i<=n;++i)
14     {
15         for(int k=1;k<=3;++k)
16         if(i>=k)
17         {
18             f[i][k][1]=max(max(f[i-1][k-1][0]+a[i],f[i-1][k-1][1]+a[i]),f[i-1][k][1]+a[i]);
19             f[i][k][0]=max(f[i-1][k][0],f[i-1][k][1]);
20         }
21     }
22     printf("%d",max(f[n][3][0],f[n][3][1]));
23     return 0;
24 }

某種數列