题解 SP283 【NAPTIME - Naptime】
【分析过程】
我们可以用一个三维数组
其中
那么对于一个时间段有两种决策:睡觉或是不睡觉
-
没有睡觉,从上个时间段取最大值
-
睡觉,上一段时间又有两种状况:在睡觉或是没有睡觉;在睡觉即可获得效益值
v_i
所以我们可以推出转移方程:
因为此题是一个环形动态规划,所以我们选择强制断环然后强制连环进行两次动态规划来消除后效性
断环,意即在时间
连环,意即在时间
【代码实现】
#include<iostream>
#include<cstring>
#define N 4000
#define set(f) memset(f,-0x3f,sizeof(f))
#define cl(a) for(int i=1;i<=n;i++) a[i][0][0]=0;
using namespace std;
int n,in[N],T,b,ans,f[N][N][2];
signed main(){
cin>>T;
while(T--){ans=0;
cin>>n>>b;
for(int i=1;i<=n;i++){
cin>>in[i];
}
set(f);cl(f);
f[1][1][1]=0;
for(int i=2;i<=n;i++){
for(int o=1;o<=i;o++){
f[i][o][0]=max(f[i-1][o][0],f[i-1][o][1]);
f[i][o][1]=max(f[i-1][o-1][1]+in[i],f[i-1][o-1][0]);
}
}
ans=max(f[n][b][0],f[n][b][1]);
set(f);cl(f);
f[1][1][1]=in[1];
for(int i=2;i<=n;i++){
for(int o=1;o<=i;o++){
f[i][o][0]=max(f[i-1][o][0],f[i-1][o][1]);
f[i][o][1]=max(f[i-1][o-1][1]+in[i],f[i-1][o-1][0]);
}
}
cout<<max(ans,f[n][b][1])<<"\n";
}
}