一个环上有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();
    
}


 

posted on 2022-10-20 16:56  towboat  阅读(17)  评论(0)    收藏  举报