一个环上有n个点,价值 a[i],现在要选择m个点,
其中连续段的第一个元素的价值不算,求总和最大?
先考虑一条链
f[i][j][0/1] ,j 是目前选择了的点的个数, 0/1 当前点i 是否选择
状态转移:
f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1])
f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+a[i])
现在考虑环的问题
这题发现只有 n 和 1 的位置要多考虑一下,因为n的取法会影响1
我们考虑 元素n是否选择 ,对应dp的边界设置
// f[1][0][0]=f[1][1][1]=0
// f[1][0][0]=0, f[1][1][1]=a[1]
#include <iostream>
#include <cstring>
using namespace std;
const int N=4000;
int n,m,a[N],f[N][N][2];
void solve(){
int i,j;
cin>>n>>m;
for(i=1;i<=n;i++) cin>>a[i];
int ans=-1e9;
memset(f,-127,sizeof f);
f[1][0][0]=f[1][1][1]=0;
for(i=2;i<=n;i++)
for(j=0;j<=m&&j<=i;j++){
f[i][j][0] =max(f[i-1][j][0],f[i-1][j][1]);
f[i][j][1] =max(f[i-1][j-1][1]+a[i],f[i-1][j-1][0]);
}
ans=max(ans,f[n][m][0]);
memset(f,-127,sizeof f);
f[1][0][0]=0,f[1][1][1]=a[1];
for(i=2;i<=n;i++)
for(j=0;j<=m&&j<=i;j++){
f[i][j][0] =max(f[i-1][j][0],f[i-1][j][1]);
f[i][j][1] =max(f[i-1][j-1][1]+a[i],f[i-1][j-1][0]);
}
ans=max(ans,f[n][m][1]);
cout<<ans<<endl;
}
signed main(){
int cas; cin>>cas;
while(cas--) solve();
}