hdu1024Max Sum Plus Plus
之前在书里看过了,但是没有做过例题,忘记它的原理了
dp[i][j]表示前i个数中选j段所能构成的最大值,(强调一下,这j段包括最后一个元素[i]的),这样第i个元素要不跟倒数第二个一起,要不独自形成一段——第j段
dp[i][j]=max(dp[i-1][j], dp[i-len[j]][j-1]+sum) len[j]表示第j段的长度,sum表示长度为len[j]的
当然得用优化算法,这是优化算法是在书里面看到的,挺巧妙的
for(i=1;i<=m;i++){
max=-INF;
for(j=i;j<=n;j++){
dp[j]=maxb(dp[j-1]+num[j],pre[j-1]+num[j]);
pre[j-1]=max;
max=maxb(max,dp[j]);
}
dp指上面的dp[i][j],pre记录第j个数前最大的dp
说说我的看完题解后,自己的敲的代码错在哪里吧
for(i=1;i<=m;i++)把这里的m改成n就错了,因为这里的m是指段数
for(j=i;j<=n;j++)把这里的j=i改成j=1就错了,因为i段的话,至少都要从第i个数开始吧
for(i=0;i<=n;i++){pre[i]=0;dp[i]=0;}把这个换成memset(pre),memset(dp)超时了,毕竟是1000000次吗,浪费太多操作了
贴上我的ACCEPT代码吧
#include "iostream" #include "string.h" #define INF 9999999; using namespace std; int maxb(int a,int b){return a>b?a:b;} int pre[1000010],dp[1000010],num[1000010]; int main(){ int m,n,i,j,max; while(cin>>m>>n){ for(i=1;i<=n;i++)cin>>num[i]; for(i=0;i<=n;i++){pre[i]=0;dp[i]=0;} for(i=1;i<=m;i++){ max=-INF; for(j=i;j<=n;j++){ dp[j]=maxb(dp[j-1]+num[j],pre[j-1]+num[j]); pre[j-1]=max; max=maxb(max,dp[j]); } } cout<<max<<endl; } }