区间dp学习笔记

退役人回来了/fad

回来学习dp(

于是先好好学习一下区间dp吧qwq

一.什么是区间dp

大家都知道什么是dp吧,dp有三部曲:定义状态,状态转移方程,边界条件。

那区间dp呢?差不多,只是它有一个范围限制,就是说它的操作只可以在这个范围内进行。

所以我们区间dp的循环有三个维度:区间长度,左端点(有了左端点和区间长度右端点就出来了对不对),断点。它们分别对应这区间dp的三个主体:阶段。状态,决策点。

干巴巴的东西说多了没用,我们直接看例题!

区间dp模板详解

找了一道模板:ybt1274.合并石子

就是纯模板题,要注意的就是合并操作的dp数组需要做初始化,因为是求最小值。

直接上核心代码qwq?

注意:要加上的得分就是两堆石子的数量总和,建议前缀和预处理这种区间和问题。


memset(dp,0x3f,sizeof(dp));
	for(int i=0;i<=n;i++)dp[i][i]=0;
	
	for(int len=2;len<=n;len++){//因为预处理过了区间长度为1的情况,所以len要从2开始qaq
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			for(int k=i;k<=j-1;k++){
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);
			}
		}
	}

既然说到有区间限制,我们就顺便说说没用区间限制的时候。

那就是这个P1090.合并果子

于是可以想到用贪心结合栈解决了qeq

以下是核心代码:


while(pq.size()>1){
		x=pq.top();
		pq.pop();
		y=pq.top();
		pq.pop();
		ans+=(x+y);
		pq.push(x+y);
	}

三.解题报告

这个绝对会更新(

1.P1880.石子合并

先来一个板子题的强化版。

和板子题不太一样的点有两个:这是一个环;要求最大和最小同时维护。

第二个简单,第一个有难度。

于是我们来拆环为链

因为对于这个环,我们随便选一个点把它拆开,就有 \(n\) 种方式。

而我们把题目中给的排列方式double一下,这个链就包含了所有拆分方式!

于是就很简单了~~

核心代码:


for(int i=1;i<=n;i++){
        cin>>a[i];
        a[n+i]=a[i];
    }
    n*=2;
    memset(minn,0x3f,sizeof(minn));
    minn[0][0]=maxn[0][0]=0;
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i];
        minn[i][i]=maxn[i][i]=0;
    }

    for(int len=2;len<=n;len++){
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            for(int k=i;k<=j-1;k++){
                minn[i][j]=min(minn[i][j],minn[i][k]+minn[k+1][j]+s[j]-s[i-1]);
                maxn[i][j]=max(maxn[i][j],maxn[i][k]+maxn[k+1][j]+s[j]-s[i-1]);
            }
        }
    }

输出操作被和谐掉了(

建议自行思考输出什么qeq

2.P1063.能量项链

绿就绿在这个环了,而环的操作已经讲了,直接和谐掉代码(bushi

3.P3146.[USACO16OPEN]248 G

非常好,这是一道和模板题基本上没有差别的题(

代码被lk鸽鸽吃掉了。

4.P4170 [CQOI2007]涂色

5.P2858 [USACO06FEB]Treats for the Cows G/S

6.P1622 释放囚犯

这个非常重要,lk鸽鸽明天再写(“钛晚了”

求监督lk鸽鸽不要咕咕咕

上一篇:Top K Frequent WOrds


下一篇:[LeetCode] 1005. Maximize Sum Of Array After K Negations