這個題目的狀態還是比較好想的,dp[i][j]表示已經睡了i個時段,最後睡在j時段的最優值,但是需要處理環的情況,我的做法是算兩次,第一次不處理環,第二次強制性要求第一個時段需要睡,然後查看dp[m][n]+a[1]的值是否更優。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=4e3+9;
int a[maxn],dp[maxn][maxn];
inline int max(int a,int b)
{
if(a>b) return a;
else return b;
}
int main()
{
// freopen("in.txt","r",stdin);
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
dp[i][j]=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int k=2,ret;k<=m;k++)
{
ret=0;
for(int i=k;i<=n;i++)
{
dp[k][i]=max(ret,dp[k-1][i-1]+a[i]);
ret=max(ret,dp[k-1][i-1]);
}
}
int ans=0;
for(int i=m;i<=n;i++)
ans=max(dp[m][i],ans);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
dp[i][j]=0;
dp[2][2]=a[2];
for(int k=3,ret;k<=m;k++)
{
ret=0;
for(int i=k;i<=n;i++)
{
dp[k][i]=max(ret,dp[k-1][i-1]+a[i]);
ret=max(ret,dp[k-1][i-1]);
}
}
if(m>=2)
ans=max(ans,dp[m][n]+a[1]);
cout<<ans<<endl;
}
return 0;
}