hdu1024 dp+滚动数组

一般思路i:划分为I端,j:前就个数

dp[i][j]=max(dp[i][j-1],dp[i-1][k])+a[j];

超时+空间

#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX  100+5
#define INF  -2100000000
using namespace std;
int dp[MAX][MAX];
int main()
{
    freopen("t.txt","r",stdin);
    int m,n,a[MAX];
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            dp[i][i]=dp[i-1][i-1]+a[i];
        }
        for(int i=1;i<=m;i++)
        {
             for(int j=i+1;j<=n;j++)
             {
                  for(int k=i-1;k<j-1;k++)
                  dp[i][j]=max(dp[i][j-1],dp[i-1][k])+a[j];
             }
        }
        int res=INF;
        for(int i=m;i<=n;i++)
        {
            if(res<dp[m][i])res=dp[m][i];
        }
        printf("%d\n",res);
    }

    return 0;
}

改进一

去掉k层循环,将d[i-1][j-1]中保存前面的最大值,一直更新,

空间仍然太大


#include <stdio.h>
#include <string.h>
#define MAX  100+5
#define INF  -2100000000
using namespace std;
int dp[MAX][MAX];
int main()
{
    freopen("t.txt","r",stdin);
    int m,n,a[MAX];
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            dp[i][i]=dp[i-1][i-1]+a[i];
        }
        for(int i=1;i<=m;i++)
        {
             dp[i-1][i]=INF;
             for(int j=i+1;j<=n;j++)
             {
                  dp[i][j]=max(dp[i][j-1],dp[i-1][j-1])+a[j]; 
             }
        }
        int res=INF;
        for(int i=m;i<=n;i++)
        {
            if(res<dp[m][i])res=dp[m][i];
        }
        printf("%d\n",res);
    }

    return 0;
}

改进二滚动数组

发现i只与i-1有关,将的dp[1][MAX]换成now[MAX],dp[0][MAX]换成pre[MAX]更好理解

dp[1][MAX]和dp[0][MAX]更适合另一种滚动方式

下次贴出来


#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX  1000005
#define INF  -2100000000
using namespace std;
int dp[2][MAX],a[MAX];
int main()
{
    //freopen("t.txt","r",stdin);
    int m,n;

    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        //dp[0][0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++)
        {
            int j;
            int temp=INF;
            for( j=i;j<=n;j++)
            {
                dp[1][j]=max(dp[1][j-1],dp[0][j-1])+a[j];
                dp[0][j-1]=temp;//0代表a[j]自成一段,故必须得至少隔开一个,所以用temp记录上次最大的与这次的a[j]隔开,例如j=3
                temp=max(temp,dp[1][j]);//下次j=4时则dp[1][4]=max(dp[1][3],dp[0][3])+a[4];而dp[0][3]=temp即。。。
            }
        }
        //int flag=m%2;
        int res=INF;
        for(int i=m;i<=n;i++)
        {
            if(res<dp[1][i])res=dp[1][i];
        }
        printf("%d\n",res);
    }

    return 0;
}


你可能感兴趣的:(dp)