正题
题目链接:http://poj.org/problem?id=2228
题目大意
有一个环,选择一段长度为n进行计算。如果第i个时间点选择不睡觉那么就会增加aiai。你也可以选择睡觉,第一个时间点不算,睡觉时间至少为m。
解题思路
我们可以分为两种情况,就是会经过1和N,和不会经过1和N。
不会经过1和N的话那么我们直接进行线性dp。
然后如果1和N连起来了话,那么我们就只剩下1和N都在睡觉了,所以我们就强制1和N在睡觉,然后两个答案的最大值就是答案。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,f[2][3831][2],a[3831],ans;
int main()
{memset(f,-127/3,sizeof(f));ans=-2147483647;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);f[1][1][1]=f[1][0][0]=0;//初始化for(int r=2;r<=n;r++){int i=r&1;for(int j=0;j<r;j++)f[i][j][0]=max(f[i^1][j][0],f[i^1][j][1]);for(int j=1;j<=r;j++)f[i][j][1]=max(f[i^1][j-1][0],f[i^1][j-1][1]+a[r]);//统计答案}ans=max(f[n&1][m][0],f[n&1][m][1]);//统计答案memset(f,-127/3,sizeof(f));f[1][1][1]=a[1];//强制睡觉for(int r=2;r<=n;r++){int i=r&1;for(int j=0;j<r;j++)f[i][j][0]=max(f[i^1][j][0],f[i^1][j][1]);for(int j=1;j<=r;j++)f[i][j][1]=max(f[i^1][j-1][0],f[i^1][j-1][1]+a[r]);}ans=max(ans,f[n&1][m][1]);//强制睡觉の统计答案printf("%d",ans);
}