POJ 2228 Naptime 環形DP

參考
https://blog.csdn.net/qq_41925919/article/details/90267224

先不考慮環的情況
dp[i][j][0]:前i個時間間隔中,已經花費了j個間隔,取得的最大值,並且第i個間隔在休息
dp[i][j][1]:前i個時間間隔中,已經花費了j個間隔,取得的最大值,並且第i個間隔不休息

轉態轉移

dp[i&1][j][1] = max(dp[(i+1)&1][j][0],dp[(i+1)&1][j][1]);
dp[i&1][j][0] = max(dp[(i+1)&1][j-1][0] + a[i],dp[(i+1)&1][j-1][1]);

最後的結果 ans = max(dp[N][B][0],dp[N][B][1])

考慮成環
由於N值過大,將輸入變成兩倍接到後面的做法不可取,tle

我們先令dp[1][1][0] = a[1],即在上一天最後一個時間段一定在sleep
然後重新運行DP,這樣除了最後一段時間和第一段時間,其他的時間段都是成環之後的正確值。
我們再來看第一段和最後一段
在最後一段sleep的情況下,第一段顯然是正確的
這是我們取 ans = max(ans,dp[N][B][0]),即最後一段時間一定在睡覺即可。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <limits.h>

using namespace std;

#define debug(x) cout<<#x<<": "<<x<<endl;

int N,B;
int a[3831];
int dp[2][3031][2];

void disp(){
    for(int i=0;i<=N;i++){
        for(int j=0;j<=B;j++){
            cout<<dp[i][j][0]<<" ";
            cout<<dp[i][j][1]<<" ";
            cout<<" ";
        }
        cout<<endl;
    }

}
int main()
{

    while( scanf("%d%d",&N,&B)!=EOF ){
        memset(dp,0x80,sizeof(dp));
        int ret = -1;
        for(int i=1;i <= N;i++){
            scanf("%d",&a[i]);
        }
        dp[1][0][1] = 0;
        dp[1][1][0] = 0;

        for( int i = 2;i <= N;i ++ ){
            for(int j = 0;j <= B;j ++){
                dp[i&1][j][1] = max(dp[(i+1)&1][j][0],dp[(i+1)&1][j][1]);
                if(j){
                    dp[i&1][j][0] = max(dp[(i+1)&1][j-1][0] + a[i],dp[(i+1)&1][j-1][1]);
                }
            }
        }

        //debug(111)
        ret = max(dp[N&1][B][0],dp[N&1][B][1]);


        memset(dp,0x80,sizeof(dp));
        dp[1][1][0] = a[1];
        for(int i=2;i<=N;i++){
            for(int j=0;j<=B;j++){
                dp[i&1][j][1] = max(dp[(i+1)&1][j][0],dp[(i+1)&1][j][1]);
                if(j){
                    dp[i&1][j][0] = max(dp[(i+1)&1][j-1][0]+a[i],dp[(i+1)&1][j-1][1]);
                }
            }
        }
        //disp();
        //ret = max(ret,dp[N&1][B][1]);
        ret = max(ret,dp[N&1][B][0]);

        cout<<ret<<endl;
    }
    return 0;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章