背景
鹰最骄傲的就是翱翔,但是鹰们互相都很嫉妒别的鹰比自己飞的快,更嫉妒其他的鹰比自己飞行的有技巧。于是,他们决定举办一场比赛,比赛的地方将在一个迷宫之中。
题目
这些鹰的起始点被设在一个N*M矩阵的左下角map[1,1]的左下角。终点被设定在矩阵的右上角map[N,M]的右上角,有些map[i,j]是可以从中间穿越的。每一个方格的边长都是100米。如图所示:
没有障碍,也没有死路。这样设计主要是为了高速飞行的鹰们不要发现死路来不及调整而发生意外。潘帕斯雄鹰冒着减RP的危险从比赛承办方戒备森严的基地中偷来了施工的地图。但是问题也随之而来,他必须在比赛开始之前把地图的每一条路都搞清楚,从中找到一条到达终点最近的路。(哈哈,笨鸟不先飞也要拿冠军)但是此鹰是前无古鹰,后无来鹰的吃菜长大的鹰--菜鸟。他自己没有办法得出最短的路径,于是紧急之下找到了学OI的你,希望找到你的帮助。
输入
首行为n,m(0<n,m<=100000),第2行为k(0<k<=1000)表示有多少个特殊的边。以下k行为两个数,i,j表示map[i,j]是可以直接穿越的。
输出
仅一行,1,1-->n,m的最短路径的长度,四舍五入保留到整数即可
样例输入
3 2
3
1 1
3 2
1 2
样例输出
383
来源
@潘帕斯雄鹰经典问题改编
解题报告:
其实就是最长上升子序列的一个变形,要走最短路就一定要尽可能地走特殊的路,所以先将这些路按照x[i] y[i]排序后,进行一次最长上升子序列就行了,蓝书里面有一道一模一样的题目。
ac程序:
var n,m,i,j,k,sum:longint;
x,y,f:array[0..1000] of longint;
procedure qsort(l,r:longint);
var i,j,now,temp,temp2:longint;
begin
i:=l; j:=r; temp:=x[(l+r) div 2]; temp2:=y[(l+r) div 2];
repeat
while (x[i]<temp) or ((x[i]=temp) and (y[i]<temp2)) do
inc(i);
while (x[j]>temp) or ((x[j]=temp) and (y[j]>temp2)) do
dec(j);
if i<=j then
begin
now:=x[i]; x[i]:=x[j]; x[j]:=now;
now:=y[i]; y[i]:=y[j]; y[j]:=now;
inc(i); dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a);
exit(b);
end;
begin
assign(input,'p4.in'); assign(output,'p4.out');
reset(input); rewrite(output);
readln(n,m);
readln(k);
for i:=1 to k do
readln(x[i],y[i]);
qsort(1,k);
{for i:=1 to k do
writeln(x[i],' ',y[i]);}
for i:=1 to k do
begin
f[i]:=1;
for j:=1 to i-1 do
if (x[i]>x[j]) and (y[i]>y[j]) then
f[i]:=max(f[i],f[j]+1);
end;
for i:=1 to k do
if f[i]>sum then sum:=f[i];
writeln(round((n+m-2*sum+sum*sqrt(2))*100));
close(input); close(output);
end.