POJ 2228 Naptime(DP+环形处理)

Posted xu-daxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2228 Naptime(DP+环形处理)相关的知识,希望对你有一定的参考价值。

题解

这题一眼望去DP。

发现自己太智障了。

这题想的是O(n^3m)的。

环形处理只会断环成链。。。。然后DP也想的不好。

我们先考虑如果除去环这题该怎么做?

dp[i][j][0/1]代表到第i小时睡了j个小时,第i小时睡了/没睡权值最大值。

初值

dp[1][1][1]=dp[1][0][0]=0;dp[i][0][0]=0;其余都是负无穷。

转移

dp[i][j][1]=max(dp[i-1][j-1][0],do[i-1[j-1][2]+w[i]);

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

目标

dp[n][m][1].dp[n][m][0];

然后考虑环,我们发现我们少考虑的只是第一个小时和上一天最后一个小时都睡觉的情况。

我们保证第一个小时和上一天最后一个小时都睡觉再做一次DP。

初值

dp[1][1][1]=a[1];dp[i][0][0]=0;其余都是负无穷。

转一样

目标

dp[n][m][1]];

这样我们做两次DP,就处理了环的情况。

注意这题空间比较少,滚一下就好了

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=4000;
 8 const int INF=199999999;
 9 int n,m,a[N],dp[2][N][2],ans;
10 int main(){
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
13     memset(dp,-63,sizeof(dp));dp[1][1][1]=dp[1][0][0]=0;
14     for(int i=2;i<=n;i++){
15         dp[i&1][0][0]=0;
16         for(int j=1;j<=min(m,i);j++){
17             dp[i&1][j][1]=max(dp[i&1^1][j-1][1]+a[i],dp[i&1^1][j-1][0]);
18             dp[i&1][j][0]=max(dp[i&1^1][j][0],dp[i&1^1][j][1]);
19         }
20     }
21     ans=max(dp[n&1][m][0],dp[n&1][m][1]);
22     memset(dp,-63,sizeof(dp));dp[1][1][1]=a[1];
23     for(int i=2;i<=n;i++){
24         dp[i&1][0][0]=0;
25         for(int j=1;j<=min(m,i);j++){
26             dp[i&1][j][1]=max(dp[i&1^1][j-1][1]+a[i],dp[i&1^1][j-1][0]);
27             dp[i&1][j][0]=max(dp[i&1^1][j][0],dp[i&1^1][j][1]);
28         }
29     }
30     printf("%d",max(ans,dp[n&1][m][1]));
31     return 0;
32 } 

 

以上是关于POJ 2228 Naptime(DP+环形处理)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2228 naptime

POJ2228 Naptime

POJ2228 Naptime

0x55. 动态规划 - 环形与后效性处理(例题详解 × 6)

poj1179 环形+区间dp

POJ 1160 Post Office(DP+经典预处理)