POJ 2373 (Dividing the Path)单调队列优化DP
来源:互联网 发布:seo招聘北京 编辑:程序博客网 时间:2024/04/30 21:58
USACO的数据
点击打开链接
另一个讲解:sunny606
数据查找:点击打开链接
根据月赛的名称,我们可以写出数据地址。比如08年一月的月赛即是:http://contest.usaco.org/JAN08 这里要注意区分大小写。
题意:
在长为L(<=1000000)的草地(可看成线段)上装喷水头,喷射是以这个喷水头为中心,喷水头的喷洒半径是可调节的,调节范围为[a,b]。要求草地的每个点被且只被一个喷水头覆盖,并且有些连续区间必须被某一个喷水头覆盖而不能由多个喷头分段完全覆盖,求喷水头的最小数
这道题,想到是DP,但是阶段与状态刚开始没搞明白。想到将每个区间当作一个阶段,这样过去。但是问题依旧很多,没有摆脱对前一个点位置的限定。其实会看题意。是要求完全覆盖,多出的洒水范围是不允许的,那么从0到len中应该是完全覆盖。那么,
定义dp[i]为覆盖[0,i]区间所需的的最小喷头数。dp[i]=min( dp[j] )+1, i-2*b<=j<=i-2*a. 因为一个喷头可以解决的范围至多是2*a~2*b,那么将其之前那些用阶段分开。前面 i-j 个都放好了...然后再在 j中放一个使得这一段全被覆盖。
因为一个喷头解决的区间必然是偶数,所以跳过所有的奇数。
还有就是奶牛喜欢的区域只能用一个喷头。那么奶牛区间就不会被完全覆盖(完全覆盖了就将区间分开了),跳过去。
原始版本TLE:
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define L 1001000#define inf 0x3f3f3f3fusing namespace std;int a,b,n,l,dp[L],Q[L],head,tail,size;int dpro(){ dp[0]=0; for(int i=2;i<=l;i+=2) { if(dp[i]<=inf) { for(int j=a;j<=b;j++) { int k=i-j-j; if(k<0) break; dp[i]=min(dp[i],dp[k]); } dp[i]++; } } if(dp[l]>=inf) return -1; return dp[l];}int main(){ while (scanf("%d%d", &n, &l)!=EOF) { scanf("%d%d", &a, &b); memset(dp,0x3f,sizeof(dp)); for(int i=0; i<n; i++) { int s, e; scanf("%d%d", &s, &e); for(int j=s+1; j<e; j++) dp[j] = inf+1;//这些区间不用考虑 } if(l&1==1) printf("-1\n"); else printf("%d\n", dpro()); } return 0;}
运用单调队列优化
转移方程dp[i]=min( dp[j] ) +1,可以看出每次只需要对 i-2*b~i-2*a 之间选取最优解,单调队列可以很好满足需求。
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define L 1001000#define inf 0x3f3f3f3fusing namespace std;int a,b,n,l,dp[L],Q[L],head,tail,siz;void in(int n){ while(head<tail && dp[Q[tail-1]]>=dp[n]) tail--;//从后往前插入 Q[tail++]=n; while(n-Q[head]>siz) head++;//保持可选区间}int dpro(){ head=tail=0; dp[0]=0; siz=2*b-2*a; for(int i=2;i<2*a;i+=2) dp[i]=inf+1; for(int i=2*a;i<=l;i+=2) { in(i-2*a); if(dp[i]<=inf) dp[i]=dp[Q[head]]+1;//刚开始这里错了,head后面写了++ } if(dp[l]>=inf) return -1; return dp[l];}int main(){ while (scanf("%d%d", &n, &l)!=EOF) { scanf("%d%d", &a, &b); memset(dp,0x3f,sizeof(dp)); for(int i=0; i<n; i++) { int s, e; scanf("%d%d", &s, &e); for(int j=s+1; j<e; j++) dp[j] = inf+1; } if(l&1==1) printf("-1\n"); else printf("%d\n", dpro()); } return 0;}
0 0
- POJ 2373 (Dividing the Path)单调队列优化DP
- poj 2373 Dividing the Path(dp+单调队列优化)
- poj2373 Dividing the Path 单调队列dp
- POJ 2373 Dividing the Path(队列dp)
- bzoj1986 [USACO2004 Dec] Dividing the Path 划区灌溉(dp+单调队列优化)
- POJ 2373 Dividing the Path DP -
- POJ 2373 Dividing the Path(线段树+dp)
- POJ 3017 Cut the Sequence (单调队列优化DP)
- Dividing(多重背包、单调队列优化dp)
- hdu 1171 Dividing 单调队列优化dp
- POJ2373 Dividing the Path——动态规划+单调队列优化
- poj 2373 单调队列优化dp
- poj 2373(单调队列优化dp)
- poj 2373 dp单调队列优化
- POJ 2373 单调队列优化DP
- POJ-2373-单调队列优化dp
- poj 1821(单调队列优化dp)
- POJ 2373 Dividing the Path
- EasyConnect
- 关于IOS8的Autolayout特性的理解以及使用
- Java的内部类(Inner Class)和嵌套类(Nested Class)的区别
- poj1149 PIGS DINIC
- Python 爬虫网页抓图保存
- POJ 2373 (Dividing the Path)单调队列优化DP
- SSH框架搭建
- unity3d学习之镜头耀斑
- 今天学了【链地址法处理冲突构造哈希表】,帮别人写了个程序。
- 在dos命令行里面INSERT中文总是报错解决办法
- 我的大学,追忆高三(永不能忘的332)
- unity3d学习之预设体
- 【软件工程】软件开发的领路者——过程模型
- 多线程中的使用共享变量的问题