首先宽搜枚举第一行每一个点,判断能否到达最后一行的每一个点,如果无解则输出,如果有解,深搜记录第一行每一个点所能覆盖到的最左端和最右端(因为每一个点所覆盖到的必是一条线段,证明略),然后贪心求需要的最少点数即可
program flow;
const
dx:array[1..4] of -1..1=(1,-1,0,0);
dy:array[1..4] of -1..1=(0,0,1,-1);
type
node=record
x,y:integer;
end;
var
max:longint;
s,n,m,ans,i,j,p,q,t,len:integer;
f:array[1..500,1..500] of boolean;
a:array[1..500,1..500] of longint;
b:array[1..500] of node;
qq:array[1..50000] of node;
procedure bfs;
var
l,r,k:longint;
begin
l:=0;
r:=1;
qq[1].x:=1;
qq[1].y:=i;
f[1,i]:=true;
while l<>r do
begin
l:=(l mod 50000)+1;
if qq[l].x=n then dec(s);
for k:=1 to 4 do
if (qq[l].x+dx[k]>n) or (qq[l].x+dx[k]<1) or (qq[l].y+dy[k]>m) or (qq[l].y+dy[k]<1) then continue
else if not f[qq[l].x+dx[k],qq[l].y+dy[k]] and (a[qq[l].x+dx[k],qq[l].y+dy[k]]<a[qq[l].x,qq[l].y]) then
begin
r:=(r mod 50000)+1;
qq[r].x:=qq[l].x+dx[k];
qq[r].y:=qq[l].y+dy[k];
f[qq[r].x,qq[r].y]:=true;
end;
end;
end;
procedure dfs(i,j:integer);
var
k:integer;
begin
f[i,j]:=true;
if i=n then
begin
if j<b[len].x then b[len].x:=j;
if j>b[len].y then b[len].y:=j;
end;
for k:=1 to 4 do
if (i+dx[k]>n) or (i+dx[k]<1) or (j+dy[k]>m) or (j+dy[k]<1) then continue
else if not f[i+dx[k],j+dy[k]] and (a[i+dx[k],j+dy[k]]<a[i,j]) then
dfs(i+dx[k],j+dy[k]);
end;
begin
assign(input,'flow.in');
reset(input);
assign(output,'flow.out');
rewrite(output);
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
fillchar(f,sizeof(f),false);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
read(a[i,j]);
readln;
end;
s:=m;
for i:=1 to m do
if not f[1,i] then bfs;
if s<>0 then
begin
writeln('0');
writeln(s);
end
else
begin
for i:=1 to m do
begin
fillchar(f,sizeof(f),false);
inc(len);
b[len].x:=501;
b[len].y:=-1;
dfs(1,i);
end;
p:=0;
q:=0;
ans:=0;
while q<m do
begin
inc(q);
p:=q;
max:=0;
for i:=1 to len do
if (b[i].x=p) and (b[i].y>max) then
begin
max:=b[i].y;
q:=b[i].y;
end;
if max=0 then dec(q,2)
else inc(ans);
end;
writeln('1');
writeln(ans);
end;
close(input);
close(output);
end.