某種數列
某種數列問題 (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 }
某種數列