写在前面
连个引言都不加就直接开
1. 区间DP状态常见模板:

f[i][j]常常表示第i个到第j个这个区间内达到题目要求,所需要的最小值(最大值)

如:

1. [石子合并](https://www.luogu.com.cn/problem/P1880)
这里的f[i][j]表示将i~j堆石头合并所需要的最小/大体力
1. [关路灯](https://www.luogu.com.cn/problem/P1220)
这里的f[i][j][0/1]表示将i~j的区间的灯完全关闭,老人站在左/右端点时剩下的灯的总功率
1. [能量项链](https://www.luogu.com.cn/problem/P1063)
这里的f[i][j]表示将i~j的珠子完全合并所能产生的最大能量

#### 总结:对于一个区间DP的状态设计来说,常常以f[i][j]进行第i个到第j个这个区间的状态设计,并辅以第三维的变量来契合题目:
如[乘积最大](https://www.luogu.com.cn/problem/P1018)的一种状态设计就是f[i][j][x]表示i~j的区间内使用x个乘号可以得到的最大值。
1. 区间DP状态转移方程模板:

f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+w(i,j));

如:

1. [石子合并](https://www.luogu.com.cn/problem/P1880)

1 f[i][j]=max(f[i][k]+f[k+1][j]+w(i,j),f[i][j])
2
3 =max(f[i][k]+f[k+1][j]+sum[j]-sum[i-1],f[i][j])
4
5 又可以进一步优化得f[i][j]=max(f[i+1][j]]+sum[j]-sum[i-1],f[i][j-1]+sum[j]-sum[i-1]);

但其本质仍然是原模板

2.[又是关路灯](https://www.luogu.com.cn/problem/P1220)

1 f[i][j][0]=
2 min(f[i+1][j][0]+(a[i+1]-a[i])*(sum[i] +sum[n]-sum[j]),f[i+1][j][1]+(a[j]-a[i])*(sum[i]+sum[n]-sum[j]));
3
4 f[i][j][1]=
5 min(f[i][j-1][0]+(a[j]-a[i])*(sum[i-1]+sum[n]-sum[j-1]),f[i][j-1][1]+(a[j]-a[j-1])*(sum[i-1]+sum[n]-sum[j-1]));这里引用了[这篇z2415445508大佬的题解](https://www.luogu.com.cn/blog/user44468/solution-p1220)~~,原因是我懒得再推DP方程。~~

实质上,利用本题条件,如石子合并一样将k优化为i+1或j-1同样是是相同模板变形。

3.[能量项链我不想举例子](https://www.luogu.com.cn/problem/P1063)

f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i+1]*a[k+1]*a[j]);


仅仅是w(i,j)稍有不同,这里更可以看出原模板变形。
1. 边界模板

边界是我们区间DP时常常漏掉的一环,因为它实在是太显而易见了( _~~然而并不是这样~~_ )

以至于在我写这里的时候根本不知道该写什么

通常来说,区间DP的边界是

(1<=i,j<=n;)
(i<=k<=j;)(=的添加与否由具体情况讨论,我见过最多的是(i<=k<j)和(i<k<=j)

懒的举例子.


4.前言总结

所谓模板,只是用来在考试时帮助你认清题目本质的,一味套板是不可取的.


# 正文

1. 下定义!


"区间动态规划是线性动归的拓展,在划分阶段时,往往是以区间的长度从小到大为阶段,逐步求解到到长度为N的区间的最优值,在枚举每一个区间的最优值时,由于当前区间内又有很多种合并方式并到到当前区间,那么就需要枚举这些合并方式中产生的值维护最优值,合并的不同,可以看作是区间划分的不同,划分时需要枚举划分的位置,即分割点。 那么对于区间类动态规划问题,往往可以将问题分解成为两两合并的形式。其解决方法是对整个问题设最优解,枚举分割点,维护最优值。
                                                                  ————[一位巨佬](https://www.cnblogs.com/SuYii/p/10988769.html)
这段话还是说得非常精彩的,揭露了区间DP的本质——小区间递推大区间。

2.实现
```cpp

for(int l=1;l<n;l++)
{
  for(int i=1,j;i+l<=2*n;i++)
  {
    j=i+l;
    f[i][j]=-0x7fffffff;
    fz[i][j]=0x7fffffff;
    for(int k=i;k<j;k++)
    {
      if(fu[k+1]==1)
      {
        f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
        fz[i][j]=min(fz[i][j],fz[i][k]+fz[k+1][j]);
      }
      if(fu[k+1]==2)
      {
          f[i][j]=max(f[i][j],f[i][k]*f[k+1][j]);
          f[i][j]=max(f[i][j],fz[i][k]*f[k+1][j]);
          f[i][j]=max(f[i][j],fz[i][k]*fz[k+1][j]);
          f[i][j]=max(f[i][j],f[i][k]*fz[k+1][j]);
          fz[i][j]=min(fz[i][j],fz[i][k]*fz[k+1][j]);
          fz[i][j]=min(fz[i][j],f[i][k]*fz[k+1][j]);
          fz[i][j]=min(fz[i][j],fz[i][k]*f[k+1][j]);
          fz[i][j]=min(fz[i][j],f[i][k]*f[k+1][j]);
}
}
}
}

以上是[多边形](https://www.luogu.com.cn/problem/P4342)我的部分代码,其中:

1. l代表一个区间的长度(这里我定义的并非标准的长度,而是图方便定义为(右端点-左端点)的值,标准的长度还要再加1;

2. i代表左端点的位置;

3. j代表左端点的位置;

4. k代表划分的位置,即分割点。



问:为什么要先枚举长度再枚举端点?
答:区间DP是由小区间递推大区间的情况,若先端点再长度会出现大区间内有小区间的情况不明了的情况。

如:f[1][3]理应=f[1][2]+f[2][3]+w(1,3);但此时f[2][3]并未求出

3. 时间复杂度

朴素的区间DP的时间复杂度为O(N^3)

4. 破环成链

[双是石子合并](https://www.luogu.com.cn/problem/P1880)

代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[5000],sum[5000],f[5000][5000],ans;
inline void read(int &s) {
int w=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-')w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
s=s*w;
return;
}
int main() {
read(n);
for(int i=1; i<=n; i++) {
read(a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=n+1; i<=2*n; i++) {
a[i]=a[i-n];
sum[i]=sum[i-1]+a[i];
}
for(int l=1; l<n; l++) {
for(int i=1,j; i+l<=2*n; i++) {
j=i+l;
f[i][j]=max(f[i+1][j]+sum[j]-sum[i-1],f[i][j-1]+sum[j]-sum[i-1]);
}
}
for(int i=1; i<=n; i++) {
ans=max(ans,f[i][i+n-1]);
}
printf("%d\n",ans);
return 0;
}

区间DP的瞎扯淡的更多相关文章

  1. 【基础练习】【区间DP】codevs1090 加分二叉树题解

    2003 NOIP TG 题目描写叙述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),当中数字1,2,3,-,n为节点编号.每一个节点都有一个分数(均为正整 ...

  2. 【BZOJ-4380】Myjnie 区间DP

    4380: [POI2015]Myjnie Time Limit: 40 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 162  Solved: ...

  3. 【POJ-1390】Blocks 区间DP

    Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5252   Accepted: 2165 Descriptio ...

  4. 区间DP LightOJ 1422 Halloween Costumes

    http://lightoj.com/volume_showproblem.php?problem=1422 做的第一道区间DP的题目,试水. 参考解题报告: http://www.cnblogs.c ...

  5. BZOJ1055: [HAOI2008]玩具取名[区间DP]

    1055: [HAOI2008]玩具取名 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1588  Solved: 925[Submit][Statu ...

  6. poj2955 Brackets (区间dp)

    题目链接:http://poj.org/problem?id=2955 题意:给定字符串 求括号匹配最多时的子串长度. 区间dp,状态转移方程: dp[i][j]=max ( dp[i][j] , 2 ...

  7. HDU5900 QSC and Master(区间DP + 最小费用最大流)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...

  8. BZOJ 1260&UVa 4394 区间DP

    题意: 给一段字符串成段染色,问染成目标串最少次数. SOL: 区间DP... DP[i][j]表示从i染到j最小代价 转移:dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k ...

  9. 区间dp总结篇

    前言:这两天没有写什么题目,把前两周做的有些意思的背包题和最长递增.公共子序列写了个总结.反过去写总结,总能让自己有一番收获......就区间dp来说,一开始我完全不明白它是怎么应用的,甚至于看解题报 ...

随机推荐

  1. Linux的磁盘管理和进程管理(入门)

    查看磁盘使用情况 df :列出文件系统整体的磁盘使用量 增加-h参数可以使得显示的容量更人性化 du:检查磁盘空间使用量---需要进入文件中查看 挂载本地磁盘或文件 mount mount /dev/ ...

  2. [JS]回调函数和回调地狱

    回调函数 小明在奶茶店点了奶茶,店员开始制作奶茶,此时"制作奶茶"与"小明等待奶茶"是一个同时进行的不同的两个事件(任务),那么,小明获取店员制作成功的奶茶是从 ...

  3. C++ 继承方式 //语法:class 子类 :继承方式 父类 //继承方式 三种: //1.公共继承 //2.保护继承 //3.私有继承

    1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 #include <ios ...

  4. C++ 结构体+数组+取随机数 案例(打印3名老师 带着 5名学生)结构体

    1 //结构体案列 2 3 #include<iostream> 4 #include<string> 5 #include<ctime> 6 using name ...

  5. PaddlePaddle之猫狗大战(本地数据集)

    新手入门PaddlePaddle的一个简单Demo--猫狗大战 主要目的在于整体了解PP用卷积做图像分类的流程,以及最最重要的掌握自定义数据集的读取方式 猫狗数据集是从网络上下载到工作目录的. 本项目 ...

  6. 算法竞赛中的常用JAVA API :HashMap 和 TreeMap(转载)

    算法竞赛中的常用JAVA API :HashMap 和 TreeMap 摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实 ...

  7. 《Python Cookbook v3.0.0》Chapter1 数据结构和算法

    感谢: https://github.com/yidao620c/python3-cookbook 如有侵权,请联系我整改. 本文章节会严格按照原书(以便和原书对照,章节标题可能会略有修改),内容会有 ...

  8. 用Ultraedit调试tk程序

    tk没有自己的编译环境,Ultraedit中仅3步就可以打造一个tk调试环境: 1. 为UE添加tcl/tk语法高亮支持:从UE的网站上下载tcl/tk的wordfile: 2. 添加编译命令到菜单中 ...

  9. SpringBoot开发十三-检查登录状态

    需求介绍-检查登录状态 防止用户知道我们的一些功能的链接,直接就进到了该页面,就像有些功能是管理员访问才能进的,就需要进行登录状态的判断. 我们知道这个功能点很多其他的功能点都需要使用,所以我们需要使 ...

  10. 自定义流式布局:ViewGroup的测量与布局

    目录 1.View生命周期以及View层级 1.1.View生命周期 1.2.View层级 2.View测量与MeasureSpec类 2.1.MeasureSpec类 2.2.父View的限制 :测 ...