现在的位置: 首页 > 综合 > 正文

HDU 1231 DP

2018年05月01日 ⁄ 综合 ⁄ 共 1206字 ⁄ 字号 评论关闭

好久没做题了,望我能跨过这道坎。

DP其实自己原先做了好久还是跟没入门一样……有点不得其法……到底是哪方面能力差……

好啦,说说想法。是看了题解还是不懂的……之前脑子里一直模拟程序是怎么走的,但是真不知道为什么这样,然后刚刚……换了一种方式……我也不知道这样靠谱不……反正……看着像对的?不对的话也是我证明的方面还不够吧。

设dp[i]为以a[i]结尾的最大子序列和。

证明:dp[i]为以a[i]结尾的最大子序列和

解:1.dp[i+1]是为以a[i+1]结尾的最大子序列和

2.dp[0]满足假设

易得2成立

即证1.

因为dp[i]是以a[i]结尾的最大子序列和,若dp[i+1]=max(dp[i]+a[i],a[i]),则2.成立。

得证。

(⊙v⊙)嗯。。。。不知道是不是这样。。。

所以这个dp的转移方程就是这个啦。

#include <stdio.h>
#define ll long long
#define maxn 10010
ll a[maxn];
typedef struct node
{
    ll val,l,r;
}node;
node dp[maxn];
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        int i,j=0;
        
        for(i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
            if(a[i]>=0) j=1;
        }
        if(!j)
        {
            printf("0 %lld %lld\n",a[0],a[n-1]);
            continue;
        }
        dp[0].val=a[0];
        dp[0].l=dp[0].r=a[0];
        for(i=1;i<n;i++)
        {
            ll tmp=dp[i-1].val+a[i];
            if(tmp>a[i])
            {
                dp[i].val=tmp;
                dp[i].r=a[i];
                dp[i].l=dp[i-1].l;
            }
            else
            {
                dp[i].val=a[i];
                dp[i].l=dp[i].r=a[i];
            }
            //printf("---%d %d %d\n",dp[i].val,dp[i].l,dp[i].r);
        }
        node sum;
        sum=dp[0];
        for(i=1;i<n;i++)
            if(dp[i].val>sum.val) sum=dp[i];

        printf("%lld %lld %lld\n",sum.val,sum.l,sum.r);
    }
    return 0;
}

************************

这里可以进行优化,两个方面,我们可以发现,每次对比只是dp[i]与dp[i-1]对比。所以不用所有的dp值都保留,只要保留pre now即可。

所以这样一来对于输入的数据也无需储存。

代码就不贴了。。。。。

原来看网络上的极简代码也不知道是怎么来的,现在自己推出来感觉真好。有的时候代码看不懂就要动手算,无厘头的代码可能是推出来的。怎么可以从一个推出来的式子上去意淫呢??!

【上篇】
【下篇】

抱歉!评论已关闭.