题意:
n个数ai组成的序列,在这n个数中选x个数,保证任意k个相连的数有1个数被选中。求这n个数中选x个数的最大和。
n <= 200。
题解:
1.dp[i][j]表示前i个数选j个数且其中包括第i个数的最大和。
2.dp[i][j] = max(dp[m][j-1] + a[j]) , m∈[max(0 , i - k) , i)。
3.初始化dp为-1e18,dp[0][0] = 0 ,所有不是由dp[0][0]递推过来的均小于0,不合法。
4.结果是max{dp[m][x]}, m∈[max(0 ,n - k + 1) , i)。
#include<bits/stdc++.h>
#define N 205
using namespace std ;
int n , k , x , m ;
long long dp[N][N] ;
int main()
{
int i , j ;
long long ans = 0 ;
long long a[N] ;
memset(dp , 0 , sizeof(dp)) ;
scanf("%d%d%d" , &n , &k , &x) ;
for(i = 1 ; i <= n ; i ++)
scanf("%lld" , &a[i]) ;
for(i = 0 ; i <= n ; i ++)
for(j = 0 ; j <= n ; j ++)
dp[i][j] = -1e18 ;
dp[0][0] = 0 ;
for(i = 1 ; i <= n ; i ++)
for(j = 1 ; j <= i ; j ++)
for(m = max(0 , i - k) ; m <= i - 1 ; m ++)
dp[i][j] = max(dp[i][j] , dp[m][j - 1] + a[i]) ;
ans = -1 ;
for(i = max(x , n - k + 1) ; i <= n ; i ++)
ans = max(ans , dp[i][x]) ;
if(ans < 0)
{
printf("-1") ;
return 0 ;
}
printf("%lld" , ans) ;
}