C. George and Job

来源:互联网 发布:机房网络同传软件 编辑:程序博客网 时间:2024/06/05 17:28

题目链接:

    http://codeforces.com/contest/467/problem/C

· 二维DP

· 题目中其实也有一个特点数字: 5000, 预示着可能使用二维dp。int f[5050][5050]可以开下,但是int f[10010][10010] 有的OJ就不行了

· 注意结果会超int 。 

dp[i][j]表示在取到第i个元素的时候取j个m长度的区间之和的最大值。

dp[i][j]可由dp[i-1][j]不添加区间得到的,或者由dp[i-m][j-1]添加一个区间得到。

遂有状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+s[i]-s[i-m]),(其中s是前缀和。)

AC  Code:

 

 1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <queue> 6 using namespace std; 7 #define LL long long 8 #define N 5050 9 int deal(int i){10 11 12 }13 LL f[N],sum[N],dp[N][N];14 int main(){15     freopen("in.txt","r",stdin);16     //freopen("out.txt","w",stdout);17     //状态转移方程: dp[i][j] = dp[i-1][j] / dp[i-m][j-1] + sum[i]-sum[i-m];18     int n,m,k;19     while(cin>>n>>m>>k){20         for(int i=1;i<=n;i++) scanf("%d",&f[i]);21         LL num=0;22         for(int i=1;i<=n;i++){23             num += f[i]; sum[i] = num; //前缀和24         }25         //printf(" sum : %d -- m :%d\n",num,m);26         memset(dp,0,sizeof(dp));27         for(int i=1;i<=n;i++){28             for(int j=1;j<=k;j++){29                 //前i个数字,取j段 m 长的数字;30                 if(i-m>=0)31                     dp[i][j] = max(dp[i-1][j],dp[i-m][j-1]+sum[i]-sum[i-m]);32             }33         }34         printf("%lld\n",dp[n][k]);35     }36 37 38     return 0;39 }
View Code

 

0 0
原创粉丝点击