单调队列优化DP能到什么程度
来源:互联网 发布:java键盘监听事件 编辑:程序博客网 时间:2024/04/27 18:46
想了一早上单调队列优化DP,总觉得不能优化到哪里去,又从来没有做过这种需要用单调队列优化的DP,于是自己用手模拟了一下实现过程,瞬间就明白了单调队列优化DP,这个DP的转移方程应该具有的性质。
单调队列很好理解,就是一个双向队列,队首队尾允许删除操作,队尾进行添加操作,维护整个队列的严格单调性,即队列中不存在相等的元素(这样时间常数小一点)。
那么用单调队列优化的DP应该具有怎样的性质呢?
假如我们有下面的DP转移方程:
f[i] = min( f[j] ) + a[i]
那么当 j 满足一个条件: Low[i] <= j <= Up[i] ,这里的 Low 和 Up 是关于 i 的单调函数,而且是单调递增的,为什么呢?联系经典的单调队列入门题: Sliding Window 想想就清楚了: 当我用下一个 Low[i] 的时候,Low[i] 必须大于等于 Low[i-1] ,因为队首涉及到了要出队列的操作,而队尾的元素上界: Up 也是必须具有单调递增的性质,因为再用队尾的元素的时候,涉及到添加元素的操作。如果还是不很明白,那么联系 Sliding Window 仔细想想这个单调队列删除插入的过程即可。很好想通的。
那么单调队列到底能优化到怎么样的程度呢?我们来看看下面的实验:
【实验方程】:
f[i] = min ( f[j] ) + a[i] ( 1<= j <= i-1 )
【实验过程】:
我做了个测试数据,不大,刚好有 10^5 个数。用传统的 o( n^2 ) 的算法铁定超时,二这个转移方程来看,我们可以不用单调队列优化到 o ( n ) 的复杂度:就是记录一个 1——i 的最小值 Min 每次计算 f[i] 的时候用 Min + a[i] 即可。
那么这道题总共就可以写出三个程序,时间复杂度分别是;
传统的二重循环判定: o( n^2 )
用最小值优化:o( n )
用单调队列优化:未知 (这就是这个实验要探讨的内容)
下面先给出实验程序:
1、传统的二重循环判定:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<ctime>
- #include<cstdlib>
- #define INF 0x7fffffff
- using namespace std;
- int main()
- {
- freopen("in.in","r",stdin);
- freopen("out.out","w",stdout);
- int n,a[100005],f[100005];
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- scanf("%d",&a[i]);
- f[1]=a[1];
- for(int i=2;i<=n;i++)
- {
- int Min=INF;
- for(int j=1;j<i;j++)
- if(Min>f[j]) Min=f[j];
- f[i]=Min+a[i];
- }
- for(int i=1;i<=n;i++)
- {
- printf("%d",f[i]);
- if(i==n) printf("\n");
- else printf(" ");
- }
- return 0;
- }
用最小值优化:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<ctime>
- #include<cstdlib>
- #define INF 0x7fffffff
- using namespace std;
- int main()
- {
- freopen("in.in","r",stdin);
- freopen("out.out","w",stdout);
- int n,a[100005],f[100005];
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- scanf("%d",&a[i]);
- f[1]=a[1];
- int Min=f[1];
- for(int i=2;i<=n;i++)
- {
- f[i]=Min+a[i];
- if(f[i]<Min) Min=f[i];
- }
- for(int i=1;i<=n;i++)
- {
- printf("%d",f[i]);
- if(i==n) printf("\n");
- else printf(" ");
- }
- return 0;
- }
用单调队列优化:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<ctime>
- #include<cstdlib>
- #define INF 0x7fffffff
- using namespace std;
- int main()
- {
- freopen("in.in","r",stdin);
- freopen("out.out","w",stdout);
- int n,a[100005],f[100005];
- int q[200000],head,tail;
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- scanf("%d",&a[i]);
- f[1]=a[1];
- tail=1; head=0; q[1]=1;
- for(int i=2;i<=n;i++)
- {
- f[i]=f[q[1]]+a[i];
- //printf("f[q[1]]=%d\n",f[q[1]]);
- //printf("f[%d]=%d\n",i,f[i]);
- while(f[i]<=f[q[tail]] && 1<=tail) tail--;
- q[++tail]=i;
- }
- for(int i=1;i<=n;i++)
- {
- printf("%d",f[i]);
- if(i==n) printf("\n");
- else printf(" ");
- }
- return 0;
- }
- 单调队列优化DP能到什么程度
- 单调队列优化DP能到什么程度(今天中午进行的实验记录)
- 单调队列优化DP能到什么程度(今天中午进行的实验记录)
- 单调队列优化DP
- 单调队列优化DP
- dp单调队列优化
- 单调队列--优化dp
- 单调队列优化dp
- 单调队列优化DP
- 单调队列优化DP
- 单调队列优化dp
- pku3709 dp单调队列优化
- POJ2373...单调队列优化DP...
- 单调队列优化dp 理解
- HDU3401 单调队列优化DP
- hdu4362 dp + 单调队列优化
- 单调队列优化的DP
- HDU4122 单调队列优化DP
- http get(swift and oc)
- JS的乘法,除法,取模,加法,减法运算
- 写给自己的flag
- Fragments
- 设置树莓派自动运行startx
- 单调队列优化DP能到什么程度
- Java并发编程:volatile关键字解析
- samba服务器的配置问题
- 百度Ueditor uParse功能Bug,生成全局CSS: li,影响全局样式, 造成网页其它部分显示混乱解决方案
- Machine learning: Trends,perspectives, and prospects读书笔记
- RadioGroup作为菜单收集
- MyEclipse10.7使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境
- spring(12) Spring的通过工厂方法配置Bean
- 第64讲Scala中的隐式类分析