HDU 1024——Max Sum Plus Plus

来源:互联网 发布:卡尔曼滤波跟踪算法 编辑:程序博客网 时间:2024/06/07 00:22

题意:一个数列分成m个子数列,求这m个子数列的最大和。
思路:动态规划。划分子问题:
要分成m个子数列,首先考虑分成m-1个子数列。再增加一个子数列的时候,可以考虑从这m-1个子数列里面找一个最大的,然后加进去一些数字。具体加数字的方案有两种。一种是在m-1个子数列的基础上新增加一个子数列。另一种是若已有了m个子数列,那么新增加的一个数字加到原有的数列中。
dp(i,m)表示分成m个子数列,将第i个数放到末尾的时候最大的和。
当划出m个子数列,将第i个数放到末尾的时候有两种情况。一种是跟i-1个数字放在一个子数列中,这样子数列的个数不会增加。另外一种是从前面i-1个数字依次做结尾,分成m-1个子数列中选一个最大的出来,将第i个数字放进去单独做一个子数列。
动态规划方程
dp(i,m)=max(dp(i-1,m)+ai,maxn(i-1,m-1)+ai)。其中maxn(i-1,m-1)表示dp(1…i-1,m-1)里面最大的一个。
代码如下:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef long long ll;const int maxn=1000005;const int minn=-2000000000;int a[maxn];int dp[maxn][2];int rec[maxn];int main(){//    freopen("data.txt","r",stdin);    int m,n;    while(scanf("%d%d",&m,&n)!=EOF){        for(int i=1;i<=n;++i){            scanf("%d",&a[i]);        }        for(int i=0;i<=n;++i){            dp[i][0]=0;            dp[i][1]=minn;            rec[i]=0;        }        int tmp=1;        for(int j=1;j<=m;++j){            int pre=tmp^1;            dp[0][tmp]=minn;            for(int i=1;i<=n;++i){                dp[i][tmp]=minn;                if(dp[i-1][tmp]>minn){                    dp[i][tmp]=dp[i-1][tmp]+a[i];                }                dp[i][tmp]=max(dp[i][tmp],rec[i-1]+a[i]);            }            rec[0]=minn;            for(int i=1;i<=n;++i){                rec[i]=minn;                if(i>0)rec[i]=max(rec[i],rec[i-1]);                rec[i]=max(rec[i],dp[i][tmp]);            }            tmp=pre;        }        int ans=minn;        for(int i=0;i<=n;++i){            ans=dp[i][tmp^1]>ans?dp[i][tmp^1]:ans;        }        printf("%d\n",ans);    }    return 0;}

最开始的时候minn开的不够小,导致错误了。。
这个代码可以优化成以为的。注意到在循环的过程中,pre完全没有用到,用处仅仅是更新tmp。另外,答案也不需要重新扫描一边,rec[n]记录的就是答案。
优化以后的代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef long long ll;const int maxn=1000005;const int minn=-200000000;int a[maxn];int dp[maxn];int rec[maxn];int main(){//    freopen("data.txt","r",stdin);    int m,n;    while(scanf("%d%d",&m,&n)!=EOF){        for(int i=1;i<=n;++i){            scanf("%d",&a[i]);        }        for(int i=0;i<=n;++i){            dp[i]=0;            rec[i]=0;        }        int tmp=1;        for(int j=1;j<=m;++j){            int pre=tmp^1;            dp[j-1]=minn;            for(int i=j;i<=n;++i){                dp[i]=max(dp[i-1]+a[i],rec[i-1]+a[i]);            }            rec[j-1]=minn;            for(int i=j;i<=n;++i){                rec[i]=minn;                rec[i]=max(rec[i],rec[i-1]);                rec[i]=max(rec[i],dp[i]);            }        }        printf("%d\n",rec[n]);    }    return 0;}
0 0
原创粉丝点击