[CODE【VS】]江哥的DP题a

来源:互联网 发布:java专业技能 编辑:程序博客网 时间:2024/06/05 01:00

原题


先来一波江哥的解题报告杀

这种方法十分的高深莫测,所以我们换一个容易理解的:

f(i,j)表示前i个选j个,且第i个必选,那么就是江哥的转移方程P.S:但是不会前缀和优化!

显然,这样的方法只能获得30分,数据十分的坑,那么优化如下:

f(i,j,0)表示前i个里面选j个且第i个不选f(i,j,1)表示前i个里面选j个且第j个选f(i,j,0)=max{f(i-1,j,0),f(i-1,j,1)};//强调,一定要取max,不然会爆0f(i,j,1)=f(i-1,j-1,0)+a[i];//这里为了优化,表示第i-1个不选的最大的分,然后累加就可以了答案存储在max{f(n,m,1),f(n,m,0)}中

所以瞬间AC,算法效率n^2;

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<algorithm>using namespace std;const int Inf=1000000000+10;long long a[1010],f[1010][1010][2];int main(){    freopen("a.in","r",stdin);    freopen("a.out","w",stdout);    int i,j,k,n,m;    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)scanf("%lld",&a[i]);    f[1][1][1]=a[1];    for(i=2;i<=n;i++)        for(j=1;j<=m;j++){            f[i][j][0]=max(f[i-1][j][1],f[i-1][j][0]);            f[i][j][1]=a[i]+f[i-1][j-1][0];        }    printf("%lld\n",max(f[n][m][0],f[n][m][1]));    return 0;}