1.(467C)http://codeforces.com/problemset/problem/467/C

题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个序列求和的最大值是多少

分析:设dp[i][j]在[j,n]范围内取了i个子序列求和所得的最大值,用sum[i]表示[1,i]的求和。转移方程为dp[i][j]=max(dp[i-1][j+m]+sum[j+m-1]-sum[j-1],dp[i][j+1]),表示要不要选择[j,j+m-1]这段为其中一个子序列

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm> 
 4 using namespace std;
 5 typedef long long ll;
 6 const ll maxn=5050;
 7 ll dp[maxn][maxn],a[maxn],sum[maxn];
 8 
 9 int main()
10 {
11     ll n,m,k,i,j,x,y,z,ans;
12     while ( scanf("%lld%lld%lld",&n,&m,&k)!=EOF ) {
13         for ( i=1;i<=n;i++ ) scanf("%lld",&a[i]);
14         sum[0]=0;
15         for ( i=1;i<=n;i++ ) sum[i]=sum[i-1]+a[i];
16         memset(dp,0,sizeof(dp));
17         ans=0;
18         for ( i=1;i<=k;i++ ) {
19             dp[i][n-i*m+1]=sum[n]-sum[n-i*m];
20             for ( j=n-i*m;j>0;j-- ) {
21                 dp[i][j]=max(dp[i-1][j+m]+sum[j+m-1]-sum[j-1],dp[i][j+1]);
22             }
23         }
24         for ( i=1;i<=n-k*m+1;i++ ) ans=max(ans,dp[k][i]);
25         printf("%lld\n",ans);
26     }
27     return 0;
28 }
467C

相关文章:

  • 2022-01-18
  • 2022-12-23
  • 2021-09-05
  • 2022-12-23
  • 2021-12-15
  • 2021-06-28
  • 2021-09-18
  • 2022-01-02
猜你喜欢
  • 2021-08-26
  • 2022-12-23
  • 2022-12-23
  • 2021-06-19
  • 2022-12-23
  • 2021-12-31
相关资源
相似解决方案