题意:给出一个带权矩阵,一条合法路径应满足下列条件:
1.跳跃方式为中国象棋中的马步.
2.每步只能跳往权值比上一步大的格子.
现在求最长的合法路径,多种方案时输出字典序最小的.
分析:POJ1088滑雪的改进版.
用f[i,j]表示从(i,j)出发的最长路径.记忆化搜索,同时更新最优方案.
code:
type recnode=record
x,y:longint;
end;
var fx:array[1..8,0..1] of longint=((-2,-1),(-1,-2),(1,-2),(2,-1)
,(2,1),(1,2),(-1,2),(-2,1));
f,num:array[0..400,0..400] of longint;
pre:array[0..400,0..400] of recnode;
n,i,j,ans,mini,minj,now:longint;
nx:recnode;
function search(x,y:longint):longint;
var o,nx,ny,tmp,len:longint;
begin
if f[x,y]>0 then exit(f[x,y]);
len:=1;
for o:=1 to 8 do
begin
nx:=x+fx[o,0];
ny:=y+fx[o,1];
if (nx>0)and(nx<=n)and(ny>0)and(ny<=n)and(num[nx,ny]>num[x,y]) then
begin
tmp:=search(nx,ny)+1;
if (tmp>len)or((tmp=len)and(num[pre[x,y].x,pre[x,y].y]>num[nx,ny])) then
begin
pre[x,y].x:=nx;
pre[x,y].y:=ny;
len:=tmp;
end;
end;
end;
f[x,y]:=len;
exit(len);
end;
begin
readln(n);
for i:=1 to n do
for j:=1 to n do read(num[i,j]);
for i:=1 to n do
for j:=1 to n do
begin
now:=search(i,j);
f[i,j]:=now;
if now>ans then
begin
ans:=now;
mini:=i;
minj:=j;
end
else if now=ans then
begin
if num[i,j]<num[mini,minj] then
begin
mini:=i;
minj:=j;
end;
end;
end;
writeln(ans);
writeln(num[mini,minj]);
while true do
begin
nx:=pre[mini,minj];
if (nx.x=0)and(nx.y=0) then break;
writeln(num[nx.x,nx.y]);
mini:=nx.x;
minj:=nx.y;
end;
end.