题意:给出一个带权矩阵,一条合法路径应满足下列条件:
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.