标签:
题解:
题意:
在数组p[n]选k个长为m的连续序列。使得和最大
题解:
1.自己的解法dp[i][j]表示所选序列一定有j,选了m个片段的最大值
首先想出来的是o(n^3)解法TLE了
for(int i=m;i<=n;i++) dp[i][1]=sum[i]-sum[i-m]; for(int i=2;i<=k;i++) for(int j=i*m;j<=n;j++) { dp[j][i]=sum[j]-sum[j-m]; ll ans=0; for(int p=(i-1)*m;p<=j-m;p++) ans=max(ans,dp[p][i-1]); dp[j][i]+=ans; }
后来发现
for(int p=(i-1)*m;p<=j-m;p++) ans=max(ans,dp[p][i-1]);
是可以优化的。是一个递增的过程,前一次用的可以在下一次继续用,降到o(n^2)了。。。
2.看了别人的题解
dp[i][j]表示前j个选i个序列.那么对于第j个数,可选,可不选
dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+sum[j]-sum[j-m]);
代码:
1.
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=5050; const int mod=1e9+7; int n,m,k; int p[maxn]; ll sum[maxn],dp[maxn][maxn]; int main() { cin>>n>>m>>k; for(int i=1;i<=n;i++) { cin>>p[i]; sum[i]=sum[i-1]+p[i]; } for(int i=m;i<=n;i++) dp[i][1]=sum[i]-sum[i-m]; for(int i=2;i<=k;i++) { int pre=(i-1)*m; ll ans=0; for(int j=i*m;j<=n;j++) { dp[j][i]=sum[j]-sum[j-m]; for(int p=pre;p<=j-m;p++) ans=max(ans,dp[p][i-1]); dp[j][i]+=ans; pre=j-m; } } ll Max=0; for(int i=k*m;i<=n;i++) Max=max(Max,dp[i][k]); cout<<Max<<endl; return 0; }
2.
#include<bits/stdc++.h> using namespace std; #define N 5002 typedef long long ll; ll sum[N]; ll dp[N][N]; int main() { int n,m,k; cin>>n>>m>>k; for (int i=1;i<=n;i++) { int x; cin>>x; sum[i]=sum[i-1]+x; } for (int i=1;i<=k;i++) { for (int j=m*i;j<=n;j++){ dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+sum[j]-sum[j-m]); } } cout<<dp[k][n]<<endl; return 0; }
Codeforces Round #267 (Div. 2) C. George and Job
标签:
原文地址:http://www.cnblogs.com/byene/p/5975528.html