POJ2228 Naptime
http://poj.org/problem?id=2228
环形DP
本来考虑把区间复制一遍,然后截取一段区间的方法,结果假掉了
实际上特判一下就行了
要么第一时刻不睡觉,直接\(DP\)
要么第一时刻睡觉,那么最后一时刻必须睡觉,再\(DP\)一次
\(Over\)了。
\(C++ Code:\)
#include<cstdio>
#include<iostream>
#define N 3835
#define INF 1000000009
using namespace std;
int dp[2][N][2];
int n,b,a[N];
int main()
{
scanf("%d%d",&n,&b);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=0;i<2;i++)
for (int j=0;j<=b;j++)
for (int k=0;k<2;k++)
dp[i][j][k]=-INF;
dp[0][0][0]=0;
for (int i=1;i<=n;i++)
{
int now=i&1;
int pre=now^1;
for (int j=0;j<=b;j++)
for (int k=0;k<2;k++)
dp[now][j][k]=-INF;
for (int j=0;j<=b;j++)
{
dp[now][j][0]=max(dp[pre][j][0],dp[pre][j][1]);
if (j)
dp[now][j][1]=max(dp[pre][j-1][0],dp[pre][j-1][1]+a[i]);
}
}
int ans=max(dp[n&1][b][0],dp[n&1][b][1]);
for (int i=0;i<2;i++)
for (int j=0;j<=b;j++)
for (int k=0;k<2;k++)
dp[i][j][k]=-INF;
dp[0][0][0]=0;
dp[1][0][0]=0;
dp[1][1][1]=a[1];
for (int i=2;i<=n;i++)
{
int now=i&1;
int pre=now^1;
for (int j=0;j<=b;j++)
for (int k=0;k<2;k++)
dp[now][j][k]=-INF;
for (int j=0;j<=b;j++)
{
dp[now][j][0]=max(dp[pre][j][0],dp[pre][j][1]);
if (j)
dp[now][j][1]=max(dp[pre][j-1][0],dp[pre][j-1][1]+a[i]);
}
}
ans=max(ans,dp[n&1][b][1]);
cout << ans << endl;
return 0;
}