cf 1077f1 基础dp 必须由初始条件递推而来

题意:

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) ;
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/87545075