HDU 1003 Max Sum

這是一道動態規劃的題目,剛學了一點動態規劃還不太熟悉,這一道題研究了很久才做出來

題目大意:
輸入n個數字,其中的數字可以按排列順序相加,找出相加值最大的子序列,輸出該最大值和起點終點

思路:
該題使用dp來做,整體的思路根據 max{dp[i]+sum, dp[i]} 來判斷, 數字相加不是一遇到負數就停止相加,而是直到發現之前相加的結果成了負數爲止。
我們可以設置變量ans存儲最終的結果、變量temp暫時存儲目前相加得到的結果,同時要記錄是從第幾個數開始相加,到第幾個數停止,每相加一次後temp都會改變,如果temp大於ans就更新結果。
這是一個邊記錄最大值邊嘗試的過程,每一次temp大於ans時更新最大值。當dp[i]是一個正數時相加後temp肯定會更大所以就毫不猶豫繼續往後相加;當dp[i]是一個負數時相加後temp肯定會變小,但只要temp仍然不是一個負數,即是暫時變小了一些但通過之後的相加還是有可能變得更大,所以我們要給dp[i]<0一個機會,j繼續往後相加,希望讓之後的數來彌補減去的這部分,就算之後不斷相加temp還是沒有減小之前大也沒關係,因爲在ans中已經存放了最大的情況。如果temp一直與負數相加最後可能會變成一個負數,此時下一個數就算是一億,相加後temp會變成一個很大的數,但仍然比一億小,負數的部分對這個一億來說卻是一個累贅,遠不如直接捨棄之前的所有數,從一億重新開始向後相加。

完整代碼如下:

#include<stdio.h>
int main() {
    int t, n ;
    int data[100005] ;
    int temp, ans, first, last, x, y ;
    scanf("%d", &t) ;
    for(int i=1; i<=t; i++) {
        scanf("%d", &n) ;
        for(int j=0; j<n; j++)
            scanf("%d", &data[j]) ;
        x = y = first = last = temp = 0 ;
        ans = -1000000 ;
        for(int j=0; j<n; j++) {
            if(temp+data[j] >= data[j]) {   //只有temp爲負數時再加多大的數都不如直接從新的數開始
                temp += data[j] ;
                last = j ;
            }
            else {
                temp = data[j] ;        //從新的點開始計
                first = last = j ;
            }
            if(temp > ans) {            //更新結果
                ans = temp ;
                x = first ;				//開始
                y = last ;				//停止
            }
        }
        printf("Case %d:\n", i) ;
        printf("%d %d %d\n", ans, x+1, y+1) ;	//因爲從0開始所以要加一
        if(i < t)
            printf("\n") ;
    }
    return 0 ;
}

總結:
dp不好搞。。。。

發佈了22 篇原創文章 · 獲贊 58 · 訪問量 7291
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章