POJ2373 Dividing the Path——动态规划+单调队列优化

本文介绍了一种使用单调队列优化动态规划状态转移方程的方法,通过维护一个单调队列,使得时间复杂度从O(n^2)降低至更优水平,特别适用于大规模数据集的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用单调队列进行动态规划。

状态转移方程很容易写出来的:

f[i]=Min{f[j]}+1(i-2*b<=j<=i-2*a)

这样,时间复杂度最坏情况下是O(n^2)的,对于n<=1000000的数据来说,程序根本无法承受

怎么办呢?单调队列很强大!

维护一个单调队列,队列里存的是按符合条件的f数组内值严格单调递增的下标值。很显然,利用队首元素就可以直接转移了。

队首元素要满足的条件很简单嘛,i-2*b<=seq[h]<=1-2*a

中间有一些小小的技巧,比如说,计算每个f值的时候,不是计算出来就将它插入到队列里,而是在计算f[i+2*a]之前把它插入队列中。

不过说了,CODE:

Program POJ2373;//By_Poetshy
Const
	maxn=1000006;
Var
	i,m,n,maxinum,mininum,j				:Longint;
	f									:Array[0..maxn]of Longint;
	b,e									:Longint;
	seq									:Array[0..maxn*2]of Longint;
	flag								:Array[0..maxn]of Boolean;
	h,t									:Longint;
	p									:Longint;

BEGIN
	readln(n,m);
	readln(mininum,maxinum);
	fillchar(flag,sizeof(flag),1);
	for i:=1 to n do
		begin
			readln(b,e);
			for j:=b+1 to e-1 do flag[j]:=false;
		end;
	fillchar(f,sizeof(f),127);
	f[0]:=0;h:=0;t:=0;
	for i:=mininum to (m >> 1) do
		begin
			p:=i << 1;
			dec(p,2*mininum);
			if (p>=0)and(f[p]<(maxlongint>>2)) then
				begin
					while (h<=t)and(f[seq[t]]>=f[p])do dec(t);
					inc(t);
					seq[t]:=p;
				end;
			inc(p,2*mininum);
			f[p]:=maxlongint;
			while (h<=t)and(seq[h]<p-2*maxinum)do inc(h);
			if (h>t)or(not flag[p]) then continue;
			f[p]:=f[seq[h]]+1;
		end;
	if f[m]<(maxlongint>>2) then writeln(f[m])else writeln(-1);
END.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值