AcWing288 休息時間(環形DP)

2021-10-10 23:49:11 字數 1690 閱讀 3185

原題鏈結

思路:

先來看只有一天的情況,dp[i][j][0]表示前i個小時休息了j個小時 並且第i個小時沒休息,dp[i][j][1]表示前i個小時休息了j個小時,並且第i個小時在休息,可以得出:

dp[i]

[j][0]

=max

(dp[

(i-1)]

[j][0]

,dp[

(i-1)]

[j][1]

);dp[i]

[j][1]

=max

(dp[

(i-1)]

[j-1][

0],dp[

(i-1)]

[j-1][

1]+u[i]

);

需要注意休息的第乙個小時不恢復體力值。

這樣的話初始化就是dp[1][0][0]=0;dp[1][1][1]=0;其餘均是-inf;

最後答案就是max(dp[n][b][0],dp[n][b][1]);

題目說的是可以迴圈,上述情況沒有包含的就是在第乙個小時就已經休息就恢復體力值的情況,只需要再跑次dp,通過修改初始化狀態得到這種情況即可。

要第乙個小時就在恢復體力值,也就是說前一天的最後乙個小時一定是已經睡覺。

初始化就是dp[1][1][1]=u[1],結果就是dp[n][b][1]。

有兩個注意點:

1.第二種情況的答案不能夠和dp[n][b][0]取max,因為這種狀態是不合法的。

2.空間不夠,因為每次狀態轉移時只會用到上乙個狀態,可以考慮用滾動陣列來優化空間。

**:

#include

using

namespace std;

typedef

long

long ll;

const

int maxn=

3840

;int u[

3840];

int n,b;

ll dp[3]

[3840][

2];int

main()

} ll res=

max(dp[n&1]

[b][0]

,dp[n&1]

[b][1]

);///memset(dp,-0x3f,sizeof dp);

for(

int i=

0;i<

2;i++

)for

(int j=

0;j<

3840

;j++

)for

(int k=

0;k<

2;k++

) dp[i]

[j][k]=-

1e18

; dp[1&

1][1

][1]

=u[1];

for(

int i=

2;i<=n;i++)}

res=

max(res,dp[n&1]

[b][1]

);printf

("%lld\n"

,res)

;return0;

}

AcWing 28 在O 1 時間刪除鍊錶結點

給定單向鍊錶的乙個節點指標,定義乙個函式在o 1 時間刪除該結點。假設鍊錶一定存在,並且該節點一定不是尾節點。樣例輸入 鍊錶 1 4 6 8 刪掉節點 第2個節點即6 頭節點為第0個節點 輸出 新鍊錶 1 4 8此題沒有給鍊錶的頭節點,只給了要刪除的節點,比較特殊。我們把要刪除的node節點的nex...

AcWing 28 在O 1 時間刪除鍊錶節點

原題鏈結 題目描述 給定單向鍊錶的乙個節點指標,定義乙個函式在o 1 時間刪除該結點。假設鍊錶一定存在,並且該節點一定不是尾節點。樣例 輸入 鍊錶 1 4 6 8 刪掉節點 第2個節點即6 頭節點為第0個節點 輸出 新鍊錶 1 4 8 解題思路 這個題給的是需要刪除的節點,並不是鍊錶的頭部,這個困擾...

2 8 後向引用

當乙個正規表示式被分組之後,每乙個組將自動被賦予乙個組號,該組號可以代表該組的表示式。其中,組號的編制規則為 從左到右 以分組的左括號 為標誌,第乙個分組的組號為1,第二個分組的組號為2,以此類推。反向引用提供查詢重複字元組的方便的方法。它們可被認為是再次匹配同乙個字串的快捷指令。後向引用可以使用數...