POJ2228 Naptime 【例题精讲】

   题意:将一天分为N小时,每小时都有一个价值w,有一头牛要睡觉,而它的睡觉是连续的,且第一小时不能算价值,即如果你睡了[a,b],则你获得的收益是w[a+1]+w[a+2]+……+w[b],而这头牛可以每天多次睡(可以理解成选若干个时间段睡觉),不过每天的睡觉总时间数不能超过B,求能获得的最大总收益。(不过值得注意的是,“1天”并不是从0~N-1,而可以是从任何一个小时开始到n小时之后,即可以从N-1睡到0)

 
      一天有N个小时,然后月落日升,昼夜往复,很显然这是一道环状结构上的DP问题,我们一般遇到环状问题时,都是把环状结构拆成一条链,来覆盖拆环方式造成的结果不同。但是这道题,把n变成二倍然后枚举,恐怕会造成时间复杂度过大。所以我们会采用另一种办法!
我们可以简单的想到转移方程
f[i][j][0]代表某天前i小时睡了j小时,且第i小时醒着所能获得的最大体力;
f[i][j][1]表示前i小时睡了j小时,且第i小时正在熟睡所能获得的最大体力!
之后呢,因为我们丢了一种情况,就是这一天的第一个小时我们是可能会处于熟睡状态的,那怎么办呢!
我们可以强行令第一小时就在熟睡状态,并且上一天的第n小时就已经开始睡眠了,这样我们只需要跟上面的结果取最优就好了!赋初值的时候呢,当然就是要把第一小时f[1][1][1]的初值赋成每天第一小时睡觉获得的最大体力咯!
 
下面上代码!
 
 
 1 //看海天一色 听风起雨落
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<string>
 6 #include<cmath>
 7 #include<cstring>
 8 #include<algorithm>
 9 using namespace std; 
10 const int MAXN=3835;
11 int f[2][MAXN][2],w[MAXN],ans=0;//f[i][j][0]代表某天前i小时睡了j小时,且第i小时醒着;
12 // f[i][j][1]表示前i小时睡了j小时,且第i小时正在熟睡!
13 //加了一个滚动数组的优化! 
14 int n,m,k;
15 int main()
16 {
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=n;i++){
19         scanf("%d",&w[i]);
20     }
21     if(m==0){
22         puts("0");return 0;
23     }
24     memset(f,-0x3f,sizeof(f));
25     f[1&1][1][1]=0;
26     f[1&1][0][0]=0;//初始化! 
27     for(int i=2;i<=n;i++){
28         for(int j=0;j<=m;j++){
29             f[i&1][j][0]=max(f[(i-1)&1][j][1],f[(i-1)&1][j][0]);//对于没熟睡的转移 
30             if(j>=1) f[i&1][j][1]=max(f[(i-1)&1][j-1][0],f[(i-1)&1][j-1][1]+w[i]);//熟睡了的转移 
31         }
32     }
33     ans=max(f[n&1][m][1],f[n&1][m][0]);
34     memset(f,-0x3f,sizeof(f));
35     f[1&1][1][1]=w[1];//强行让牛在第一个小时就熟睡!这是前文规划中没有的部分;
36     for(int i=2;i<=n;i++){//执行第2次dp,对上面已经执行过的dp作补充! 
37         for(int j=0;j<=m;j++){
38             f[i&1][j][0]=max(f[(i-1)&1][j][1],f[(i-1)&1][j][0]);
39             if(j>=1) f[i&1][j][1]=max(f[(i-1)&1][j-1][0],f[(i-1)&1][j-1][1]+w[i]);
40         }
41     } 
42     ans=max(ans,f[n&1][m][1]);//两次取最优! 
43     printf("%d",ans);
44     puts("");
45     return 0;
46 }
View Code

 

posted @ 2018-04-05 17:04  杜宇一声  阅读(479)  评论(0编辑  收藏  举报