P1951 [GDFZOJ] 徒步旅行

题目意思是给你一个坐标轴 , 其中 \(C_{x,y}=\max\{x,y\}\) , 要我们走完一种 \(C\) 的区域才能走下一个 \(C\) 的区域 , 求从 \((0,0)\)\((end,end)\) 经过一些点的最小路径, 值都为曼哈顿距离。点数为 \(3 \times 10^5\)

考虑一个 \(C\) 式矩阵 :

1 2 3 4
2 2 3 4
3 3 3 4
4 4 4 4

那么我们可以知道的是 , 每一层至少有一个不会改变的贡献 , 就是最左下角和最左上角的距离。然后问题变为上一层到下一层过渡总和的最小值。

我们就可以直接 \(\texttt{DP}\) 解决问题。\(\texttt{DP}\) 每一个最左下角点和最右上角点到下一个这样的点的最小值 , 记住贡献和贡献目标要相反。

Const
	total=300000+10;

var
	tiny,huge:array[-1..total,1..2] of longint;
	fuck:array[-1..total,1..2] of longint;
	i,j,l,r,a,b,n,ans,maxn,recf:longint;
	bz:boolean;

function Max(a,b:longint):longint; begin if a>b then exit(a); exit(b); end;

function Min(a,b:longint):longint; begin if a<b then exit(a); exit(b); end;

function Dis(a,b,x,y:longint):longint; begin exit(abs(a-x)+abs(b-y)); end;

procedure Swap(var a,b:longint);var t:longint; begin t:=a; a:=b; b:=t; end;

begin
	read(n);
	for i:=1 to n do begin tiny[i,2]:=maxlongint; huge[i,1]:=maxlongint; end;
	for i:=1 to n+1 do
	begin
		if i<=n then read(l,r) else begin l:=0; r:=0; end;
                recf:=Max(l,r); maxn:=Max(maxn,recf);
		if (tiny[recf,2]>r) then begin tiny[recf,1]:=l; tiny[recf,2]:=r; end;
		if (huge[recf,1]>l) then begin huge[recf,1]:=l; huge[recf,2]:=r; end;
	end;
	for i:=1 to maxn do
	begin
		if tiny[i,2]=maxlongint then tiny[i,2]:=0;
		if huge[i,1]=maxlongint then huge[i,1]:=0;
	end;
	for i:=1 to maxn do for j:=1 to 2 do fuck[i,j]:=maxlongint;
    fuck[0,1]:=0; fuck[0,2]:=0; ans:=maxlongint;
	for i:=0 to maxn do
	begin
		a:=Dis(tiny[i,1],tiny[i,2],tiny[i-1,1],tiny[i-1,2]);
		b:=Dis(tiny[i,1],tiny[i,2],huge[i-1,1],huge[i-1,2]);
		l:=Dis(huge[i,1],huge[i,2],tiny[i-1,1],tiny[i-1,2]);
		r:=Dis(huge[i,1],huge[i,2],huge[i-1,1],huge[i-1,2]);
        recf:=Dis(tiny[i,1],tiny[i,2],huge[i,1],huge[i,2]);
		fuck[i,1]:=Min(fuck[i-1,1]+l,fuck[i-1,2]+r)+recf;
		fuck[i,2]:=Min(fuck[i-1,1]+a,fuck[i-1,2]+b)+recf;
	end;
	ans:=Min(fuck[i,1]+Dis(0,0,tiny[i,1],tiny[i,2]),fuck[i,2]+Dis(0,0,huge[i,1],huge[i,2]));
	writeln(ans);
end.
posted @ 2019-09-21 15:59  _ARFA  阅读(131)  评论(0编辑  收藏  举报