您的位置:首页 > 其它

暑期dp46道(18)--HDOJ 1024 Max Sum Plus Plus

2016-08-10 14:21 447 查看
题目链接:HODJ 1024

这题花的时间蛮多的,不过没有浪交,就是之前有几位做过的说这题很“巧”,需要费时间,我才没敢轻易交,大概花了一天时间交了一发,A掉,还多开了内存,尴尬,不过确实挺巧的,dp降低复杂度的妙用或许就在这吧;

题意:相信大家都能看懂,就是给定一个序列a1,a2.....an;求把它分为m个单独序列的最大值;

题解:这题状态方程其实是不难想的,但是可能会被顾忌到复杂度,刚开始就想着直接有效的算法,结果怎么都找不到,dp还是应该先找解法,再优化的。

对于一个长为i的序列,分成j个单独序列的最优解:

a[i]在这j个序列内 

dp[i][j]=max(dp[i-1][j]+a[i],dp[k][j-1]+a[i])(k>=0&&k<i)

然后对于dp[k][j-1]这段最大值 只要记录下就好了

代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>//sort();
#include<climits>
using namespace std;
#define debug 0
#define M(a) memset(a,0,sizeof(a))
#define Max(a,b) ((a>b)?a:b)

const int maxn = 1000000+5;
int data[maxn],dp[maxn],temp[maxn];
int n,m;

void Do()
{
int ans;
for(int i = 1;i <= n;i++)
{
ans = INT_MIN;
for(int j = i;j <= m;j++)//这里dp[j]表示当前长为j的序列分为i段的最优解
{
dp[j] = Max(dp[j-1] + data[j],temp[j-1] + data[j]);//temp[j-1]保存的是长为1->j-1的序列分为
temp[j-1] = ans; //i-1段的最优解
ans = Max(ans,dp[j]);//ans保存长为i->j的序列分为i段最优解Max,即为最终最优解
}
}
printf("%d\n",ans);
}
int main()
{
#if debug
freopen("in.txt","r",stdin);
#endif//debug
while(~scanf("%d%d",&n,&m))
{
M(dp);
M(temp);
for(int i = 1;i <= m;i++)
{
scanf("%d",&data[i]);
}
Do();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU-dp-算法 dp