题目:http://poj.org/problem?id=2228
环形dp。开一维记录当前最后一份时间是否在睡。很精妙地分两类。
1.正常从1到n线性dp。
2.上边只有一种情况未覆盖:第一份时间就已经在熟睡。这要求最后一份时间必须在睡。规定一下再dp一遍即可。(别忘特判b==1)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,b; long long u[3835],d[3835][2],ans; int main() { scanf("%d%d",&n,&b); for(int i=1;i<=n;i++)scanf("%lld",&u[i]); memset(d,-2,sizeof d); d[0][0]=0;d[1][1]=0; for(int i=2;i<=n;i++) for(int j=b;j>=0;j--) { d[j][0]=max(d[j][0],d[j][1]); if(j>0)d[j][1]=max(d[j-1][0],d[j-1][1]+u[i]); } ans=max(d[b][0],d[b][1]); memset(d,-2,sizeof d); d[1][1]=u[1]; for(int i=2;i<=n;i++) for(int j=b;j>=0;j--) { d[j][0]=max(d[j][0],d[j][1]); if(j>0)d[j][1]=max(d[j-1][0],d[j-1][1]+u[i]); } if(b>1)ans=max(ans,d[b][1]); printf("%lld",ans); return 0; }