HDU 1024 MAX sum plus plus
传送们:http://blog.sina.com.cn/s/blog_677a3eb30100jxqa.html
Author
JGShining(极光炫影)
思路:
dp[i][j]表示前j个元素分成i段的最优解,同时这个最优解是由a[j]元素结束的。
转移方程是dp[i][j]=max{f[i][j-1]+a[j],f[i-1][k]+a[j],(i-1<=k<j)} (i<=j<=n-m+i)
其中j的上下界的确定比较麻烦。现在分别解释上界和下界:
上界:dp[i][j]中,如果j=i-1,意思就是在前面i-1个元素中分成i段,这个是不可能实现的。
下界:如果m=n=4,这时dp[2][4]求出来了,意思是前面的四个元素分成了两段,当是还有两段要分,
这是其中一个特例的状态转移表 m=4,n=6 ,-1 4 -2 3 -2 3
没有填的说明不用算。
很显然dp[i][i]=dp[i-1][i-1]+a[i],
所以对角线上面有:
假如框中的元素是dp[i][j],画圈的元素表示的是,左边那个是dp[i][j-1],上面的几个是dp[i-1][k](i-1<=k<j)} ,这个就是上面的转移方程的表格表示法。
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; __int64 a[1000010]; __int64 dp[2][1000010],ans;//设置滚动数组 int n,m; __int64 MAX(__int64 a,__int64 b) { return a>b?a:b; } int main() { int i,j; while(scanf("%d %d",&m,&n)!=EOF) { for(i=1;i<=n;i++) { dp[0][i]=dp[1][i]=0; scanf("%I64d",&a[i]); } int pos=1; for(i=1;i<=m;i++) { dp[pos][i]=dp[pos^1][i-1]+a[i];//滚动数组,要进行初始化 __int64 max=dp[pos^1][i-1]; for(j=i+1;j<=n-m+i;j++) { max=MAX(max,dp[pos^1][j-1]); dp[pos][j]=MAX(dp[pos][j-1]+a[j],max+a[j]); } pos^=1; } pos^=1; ans=-99999999; for(i=m;i<=n;i++) { if(dp[pos][i]>ans) { ans=dp[pos][i]; } } cout<<ans<<endl; } return 0; }
posted on 2011-07-27 16:59 lonelycatcher 阅读(2212) 评论(0) 编辑 收藏 举报