刺杀大使{二分答案+dfs+人工栈}

{转自 仕林} {O(n*m*logmax)}
 
 
program murder;
var n,m,max:longint;
    p:array[1..1010,1..1010]of longint;
    v:array[1..1010,1..1010]of boolean;
    sx,sy:array[0..1000010]of longint;

function dfs(x,y,c:longint):boolean;
var u,w:longint;
begin
  sx[0]:=1;sy[0]:=1;
  sx[sx[0]]:=x;sy[sy[0]]:=y;
  while sx[0]<>0 do
  begin
   u:=sx[sx[0]];w:=sy[sy[0]];
   v[u][w]:=true;
   if u=n then exit(true);
   if (not v[u+1][w])and(p[u+1][w]<=c) then
    begin
      inc(sx[0]);inc(sy[0]);
      sx[sx[0]]:=u+1;sy[sy[0]]:=w;
      continue;
    end;
   if (w<m)and(not v[u][w+1])and(p[u][w+1]<=c) then
    begin
      inc(sx[0]);inc(sy[0]);
      sx[sx[0]]:=u;sy[sy[0]]:=w+1;
      continue;
    end;
   if (w>1)and(not v[u][w-1])and(p[u][w-1]<=c) then
    begin
      inc(sx[0]);inc(sy[0]);
      sx[sx[0]]:=u;sy[sy[0]]:=w-1;
      continue;
    end;
   if (u>1)and(not v[u-1][w])and(p[u-1][w]<=c) then
    begin
      inc(sx[0]);inc(sy[0]);
      sx[sx[0]]:=u-1;sy[sy[0]]:=w;
      continue;
    end;
   dec(sx[0]);dec(sy[0]);
  end;
  exit(false);
end;

procedure init;
var i,j:longint;
begin
  assign(input,'murder10.in');
  reset(input);
  assign(output,'murder.out');
  rewrite(output);
  read(n);read(m);
  max:=-maxlongint;
  for i:=1 to n do
    for j:=1 to m do
      begin
       read(p[i][j]);
       if max<p[i][j] then max:=p[i][j];
      end;
end;

procedure main;
var l,r,mid,i:longint;
    f:boolean;
begin
  l:=0;r:=max;
  while l<r do
   begin
     mid:=(l+r)shr 1;
     fillchar(v,sizeof(v),false);
     f:=false;
     for i:=1 to m do v[1][i]:=true;
     for i:=1 to m do
      if dfs(1,i,mid) then begin f:=true;break;end;
     if f then r:=mid
          else l:=mid+1;
   end;
  write(l);
  close(input);
  close(output);
end;

begin
  init;
  main;
end.


下面附上我的仿真代码{WA}{能否指教?}
type s=record

  x,y:longint;

  end;

var

  n,m,i,j,l,r,mid,max:longint;

  dx:array[1..4] of integer=(-1,1,0,0);

  dy:array[1..4] of integer=(0,0,-1,1);

  flag:boolean;

  p:array[1..1000,1..1000] of longint;

  used:array[1..1000,1..1000] of boolean;

  stack:array[0..1000000] of s;

function dfs(x,y,w:longint):boolean;

var

  tx,ty,top,j:longint;

begin

  fillchar(used,sizeof(used),false);

  for j:=1 to m do used[1,j]:=true;

  stack[1].x:=x;

  stack[1].y:=y;

  top:=1;

  while top>0 do

    begin

      used[stack[top].x,stack[top].y]:=true;

      if stack[top].x=n then exit(true);

      tx:=stack[top].x+dx[1];

      ty:=stack[top].y+dy[1];

      if (tx>=1)and(tx<=n)and(ty>=1)and(ty<=m)and(not used[tx,ty])and(p[tx,ty]<=w) then

        begin

          inc(top);

          stack[top].x:=tx;

          stack[top].y:=ty;

          continue;

        end;

      tx:=stack[top].x+dx[2];

      ty:=stack[top].y+dy[2];

      if (tx>=1)and(tx<=n)and(ty>=1)and(ty<=m)and(not used[tx,ty])and(p[tx,ty]<=w) then

        begin

          inc(top);

          stack[top].x:=tx;

          stack[top].y:=ty;

          continue;

        end;

      tx:=stack[top].x+dx[3];

      ty:=stack[top].y+dy[3];

      if (tx>=1)and(tx<=n)and(ty>=1)and(ty<=m)and(not used[tx,ty])and(p[tx,ty]<=w) then

        begin

          inc(top);

          stack[top].x:=tx;

          stack[top].y:=ty;

          continue;

        end;

      tx:=stack[top].x+dx[4];

      ty:=stack[top].y+dy[4];

      if (tx>=1)and(tx<=n)and(ty>=1)and(ty<=m)and(not used[tx,ty])and(p[tx,ty]<=w) then

        begin

          inc(top);

          stack[top].x:=tx;

          stack[top].y:=ty;

          continue;

        end;

      dec(top);

    end;

  exit(false);

end;

begin

  assign(input,'work.in');

  reset(input);

  assign(output,'work.out');

  rewrite(output);

  read(n,m);

  max:=0;

  for i:=1 to  n do

    for j:=1 to m do

      begin

         read(p[i,j]);

         if max<p[i,j] then max:=p[i,j];

      end;

  l:=1;r:=max;

  while l<>r do

    begin

      mid:=(l+r) shr 1;

      flag:=false;

      for j:=1 to m do

        if dfs(1,j,mid) then

          begin

            flag:=true;

            break

          end;

      if flag=true then r:=mid

      else l:=mid+1;

    end;

  writeln(l);

  close(input);

  close(output);

end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值