区间动态规划详解

前段时间遇到石子合并问题,看着题解A了,以为学会了区间DP,再次遇到能量项链这个问题的时候大脑还是一片空白,只能重新认识一下区间动态规划了。

翻过很多博客,基本上都是题解,真正对区间动态规划本身的讲解几乎没有,可能是我没找到吧。

区间动态规划,顾名思义,就是动态规划过程中求一个区间的最优解。通过将一个大的区间分为很多个小的区间,求其小区间的解,然后一个一个的组合成一个大的区间而得出最终解,有没有发现,这完全就是分治的思想。

动态规划三部曲:

1.状态:用dp[i][j]表示区间(i,j)的最优解

2.状态转移:

    最常见的写法:     dp[i][j]=max/min(dp[i][j],dp[i][k]+dp[k+1][j]+something)

    理解:区间(i,j)的最优解就等于 区间(i,j)   同 (i,k)和区间(k+1,j)合并后的值   比谁更优。

3.初始化: dp[i][i]=0/other (i=1->n)

 为什么这么做呢?很好理解,就是只包含自己本身的时候,也就是区间长度为1,值肯定是确定的。

怎么从小到大的合并区间呢?

有两种最常见的写法:

第一种:

 for(r=2;r<=n;r++)//r:区间右端点,l:区间左端点
        for(l=r-1;l>=1;l--)
            for(k=l;k<r;k++)
                dp[l][r] = max/min(dp[l][r],dp[l][k]+dp[k+1][r]+something);

第二种:

for (int len=2;len<=n;len++)//len:长度 ,l:左区间断点,r:又区间端点
    for (int l=1;l+len-1<=n;l++) //保证(l,r)的长度为len,且不越界
    {
        int r=l+len-1;
        for (int k=l;k<=r;k++)
            dp[l][r]=max/min(dp[l][r],dp[l][k]+dp[k+1][r]+something)
    }

第一种是个人比较喜欢也是很容易想到的。理解起来很简单:遍历以r为终点,从1到r的所有子区间。

这种做法的一个好处就是dp[l][r]存的一定是r为右区间的每一步的最优解。

第二种是用的人数最多的。 理解:从区间长度为2–n,每次遍历固定长度的区间。比如,len=2时,遍历(1,2)(2,3)…(n-1,n)。这样也能遍历完所有的情况。

当然还有其他写法,例如:

	for (int len=1;len<=n;len++) //枚举长度
        for (int l=1;l<n-len;l++) //从第i个石子开始
            for (int j=l;j<l+len;j++)
                dp[l][l+len]=max(dp[l][l+len],dp[l][j]+dp[j+1][l+len])+somethong;

思维都大同小异,只要保证是从小区间遍历到大区间就没问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值