P1107 [BJWC2008]雷涛的小猫

题目地址

显而易见 这是一道DP的题目
二维数组a[i][j]代表i棵树j高度有多少个柿子
dp[i][j]代表i棵树j高度最多能吃到多少柿子
i棵树j高度 可以由别的树k从j-Delta位置跳过来
也可以从i棵树j-1位置过来
所以状态转移方程为
dp[i][j]=a[i][j]+max(dp[i][j-1],dp[k][j-Delta])

看看输入数据 n h<2000
如果直接写dp 时间复杂为O(n^3)
最差情况 大概要计算80亿次 时间只有2秒 超时概率很大
我提交了下代码 很不幸超时了

#include <stdio.h>

int main(){
    int n,h,delta;
    scanf("%d %d %d",&n,&h,&delta);
    int i,j,k;
    int** input=new int*[n];
    int** dp=new int*[n];
    for( i=0;i<n;i++)
    {
        input[i]=new int[h];
        dp[i]=new int[h];
        for(j=0;j<h;j++)
        {
            input[i][j]=0;
            dp[i][j]=0;
        }
    }

    int ni,num;
    for( i=0;i<n;i++)
    {
        scanf("%d",&ni);
        for(j=0;j<ni;j++)
        {
            scanf("%d",&num);
            input[i][num-1]++;
        }
    }


    for( i=0;i<n;i++)
    {
        dp[i][0]=input[i][0];
    }

    for(j=1;j<h;j++){
        for(i=0;i<n;i++)
        {
            int max=dp[i][j-1];
            if(j>=delta)
            {
                for(k=0;k<n;k++)
                {
                    if(k!=i)
                    {
                        if(max<dp[k][j-delta])
                        {
                            max=dp[k][j-delta];
                        }
                    }
                }
            }
            dp[i][j]=max+input[i][j];      
        }
    }

    int max=0;
    for( i=0;i<n;i++)
    {
        if(max<dp[i][h-1])
        {
            max=dp[i][h-1];
        }
    }
    printf("%d\n",max);

    for( i=0;i<n;i++)
    {
        delete dp[i];
        delete input[i];
    }
    delete dp;
    delete input;
    return 0;
}

需要对该方法进行优化
状态转移方程
dp[i][j]=a[i][j]+max(dp[i][j-1],dp[k][j-Delta])
很明显我们只要知道j-Delta 高度所有树的最大值就可以了
不需要把每个树都遍历一遍
所以建立一个一维数组 dph[j]=max(dp[i][j])
状态转移方程变成
dp[i][j]=a[i][j]+max(dp[i][j-1],dph[j-Delta])
这样时间复杂度变成了O(n^2)

#include <stdio.h>

int main(){
    int n,h,delta;
    scanf("%d %d %d",&n,&h,&delta);
    int i,j,k;
    int** input=new int*[n];
    int** dp=new int*[n];
    int* dph=new int[h];
    for( i=0;i<n;i++)
    {
        input[i]=new int[h];
        dp[i]=new int[h];
        for(j=0;j<h;j++)
        {
            input[i][j]=0;
            dp[i][j]=0;
            dph[j]=0;
        }
    }

    int ni,num;
    for( i=0;i<n;i++)
    {
        scanf("%d",&ni);
        for(j=0;j<ni;j++)
        {
            scanf("%d",&num);
            input[i][num-1]++;
        }
    }


    for( i=0;i<n;i++)
    {
        dp[i][0]=input[i][0];
        if(dph[0]<input[i][0])
        {
            dph[0]=input[i][0];
        }
    }

    for(j=1;j<h;j++){
        int maxh=0;
        for(i=0;i<n;i++)
        {
            int max=dp[i][j-1];
            if(j>=delta)
            {
                if(max<dph[j-delta])
                {
                    max=dph[j-delta];
                }
            }
            dp[i][j]=max+input[i][j];
            if(maxh<dp[i][j])
            {
                maxh=dp[i][j];
            }      
        }
        dph[j]=maxh;
    }
    printf("%d\n",dph[h-1]);

    for( i=0;i<n;i++)
    {
        delete dp[i];
        delete input[i];
    }
    delete dp;
    delete input;
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容