二、搜索

1.红与黑(codevs2806)

题目网址:http://codevs.cn/problem/2806/

代码:

var
 s:array[0..21,0..21] of char;
 i,j,sum,w,c,x,y:longint;
procedure m(a,b:longint);
begin
 inc(sum);
 s[a,b]:='#';
 if(s[a+1,b]='.') then
    begin
    m(a+1,b);
    end;
 if(s[a-1,b]='.') then
    begin
    m(a-1,b);
    end;
 if(s[a,b+1]='.') then
    begin
    m(a,b+1);
    end;
 if(s[a,b-1]='.') then
    begin
    m(a,b-1);
    end;
end;
begin
 readln(w,c);
 while (w<>0) and (c<>0) do
    begin
      fillchar(s,sizeof(s),0);
      for i:=1 to c do
      begin
        for j:=1 to w do
          begin
            read(s[i,j]);
            if (s[i,j]='@') then
              begin
                x:=i;
                y:=j;
              end;
          end;
        readln;
      end;
        sum:=0;
        m(x,y);
        writeln(sum);
      readln(w,c);
    end;
end.




2.八数码难题

题目网址:http://codevs.cn/problem/1225/

分析:

这题值得说的是康托展开。全排列与整数的映射,挺实用的。

接下来就是普通的BFS了。和用HASH表判重

代码:

type arr=array [1..9] of longint;


var a:array [1..30000] of arr;
    fac:array [0..10] of longint;
    step,space:array [0..30000] of longint;
    i,front,tail:longint;
    s:string;
    hash:array [1..400000] of boolean;


function cantor(a:arr):longint;
var i,j:longint;
    k:arr;
begin
  fillchar(k,sizeof(k),0);
  cantor:=0;
  for i:=1 to 9 do
  for j:=i+1 to 9 do
  if a[i]>a[j] then inc(k[i]);
  for i:=1 to 9 do cantor:=cantor+k[i]*fac[9-i];
  cantor:=cantor+1;
end;


procedure exchange(s,t:longint);
var tmp:arr;
    num,fun,i:longint;
begin
  tmp:=a[front];
 fun:=tmp[s]; tmp[s]:=tmp[t];tmp[t]:=fun;
  num:=cantor(tmp);
  if num=46686 then
  begin
    write(step[front]+1);
    halt;
  end;
  if not hash[num] then
  begin
    inc(tail);
    a[tail]:=tmp;
    hash[num]:=true;
    space[tail]:=t;
    step[tail]:=step[front]+1;
  end;
end;


begin
  fillchar(hash,sizeof(hash),false);
  readln(s);
  fac[0]:=1;
  for i:=1 to 9 do fac[i]:=i*fac[i-1];
  for i:=1 to 9 do
  begin
    a[1][i]:=ord(s[i])-ord('0');
    if a[1][i]=0 then space[1]:=i;
  end;
  hash[cantor(a[1])]:=true;
  front:=1;
  tail:=1;
  step[1]:=0;
  while front<=tail do
  begin
    if space[front]<=6 then exchange(space[front],space[front]+3);
    if space[front]>=4 then exchange(space[front],space[front]-3);
    if ((space[front]-1)mod 3)>0 then exchange(space[front],space[front]-1);
    if ((space[front]-1)mod 3)<2 then exchange(space[front],space[front]+1);
    inc(front);
  end;
end.



3.武士风度的牛

题目网址:http://codevs.cn/problem/1411/

分析:利用BFS求无权最短路径

代码:

var
  a:array[1..150,1..150] of char;
  b:array[1..22500,1..3] of longint;
  i,j,m,n,x,y,m1,n1,m2,n2,f,r:longint;
begin
  readln(n,m);
  for i:=1 to m do
  begin
    for j:=1 to n do
    begin
      read(a[i,j]);
      if a[i,j]='K' then
      begin
        m1:=i;
        n1:=j;
      end;
      if a[i,j]='H' then
      begin
        m2:=i;
        n2:=j;
      end;
    end;
    readln;
  end;
  f:=1;
  r:=1;
  a[m2,n2]:='*';
  b[f,1]:=m2;
  b[f,2]:=n2;
  b[f,3]:=0;
  repeat
    x:=b[f,1];
    y:=b[f,2];
    if (x=m1) and (y=n1) then
    begin
      writeln(b[f,3]);
    end;
    if (x-1>0) and (y-2>0) and (a[x-1,y-2]<>'*') then
    begin
      inc(r);
      b[r,1]:=x-1;
      b[r,2]:=y-2;
      b[r,3]:=b[f,3]+1;
      a[x-1,y-2]:='*';
    end;
    if (x-2>0) and (y-1>0) and (a[x-2,y-1]<>'*') then
    begin
      inc(r);
      b[r,1]:=x-2;
      b[r,2]:=y-1;
      b[r,3]:=b[f,3]+1;
      a[x-2,y-1]:='*';
    end;
    if (x-2>0) and (y+1<n) and (a[x-2,y+1]<>'*') then
    begin
      inc(r);
      b[r,1]:=x-2;
      b[r,2]:=y+1;
      b[r,3]:=b[f,3]+1;
      a[x-2,y+1]:='*';
    end;
    if (x-1>0) and (y+2<n) and (a[x-1,y+2]<>'*') then
    begin
      inc(r);
      b[r,1]:=x-1;
      b[r,2]:=y+2;
      b[r,3]:=b[f,3]+1;
      a[x-1,y+2]:='*';
    end;
    if (x+1<m) and (y-2>0) and (a[x+1,y-2]<>'*') then
    begin
      inc(r);
      b[r,1]:=x+1;
      b[r,2]:=y-2;
      b[r,3]:=b[f,3]+1;
      a[x+1,y-2]:='*';
    end;
    if (x+2<m) and (y+1<n) and (a[x+2,y+1]<>'*') then
    begin
      inc(r);
      b[r,1]:=x+2;
      b[r,2]:=y+1;
      b[r,3]:=b[f,3]+1;
      a[x+2,y+1]:='*';
    end;
    if (x+2<m) and (y-1>0) and (a[x+2,y-1]<>'*') then
    begin
      inc(r);
      b[r,1]:=x+2;
      b[r,2]:=y-1;
      b[r,3]:=b[f,3]+1;
      a[x+2,y-1]:='*';
    end;
    if (x+1<m) and (y+2<n) and (a[x+1,y+2]<>'*') then
    begin
      inc(r);
      b[r,1]:=x+1;
      b[r,2]:=y+2;
      b[r,3]:=b[f,3]+1;
      a[x+1,y+2]:='*';
    end;
    inc(f);
  until f>r;
end.


4.最大黑区域

描写叙述:

二值图像是由黑白两种像素组成的矩形点阵,图像识别的一个操作是求出图像中最大黑区域的面积。请设计一个程序完毕二值图像的这个操作。黑区域由黑像素组成。一个黑区域中的每一个像素至少与该区域中的还有一个像素相邻,规定一个像素仅与其上、下、左、右的像素相邻。两个不同的黑区域没有相邻的像素。

一个黑区域的面积是其所包括的像素的个数。

输入格式:

输入由多个測试例组成。

每一个測试例的第一行含两个整数n和m, (1 <=n,m<=100), 分别表示二值图像的行数与列数,后面紧跟着n行,每行含m个整数0或1,当中第i行表示图像的第i行的m个像素,0表示白像素,1表示黑像素。

同一行的相邻两个整数之间用一个空格隔开,两个測试例之间用一个空行隔开,最后一个測试例之后隔一个空行,再接的一行含有两个整数0,标志输入的结束。

输出格式:

每一个測试例相应一行输出,含一个整数,表示相应的图像中最大黑区域的面积。

输入例子:

5 6
0 1 1 0 0 1
1 1 0 1 0 1
0 1 0 0 1 0
0 0 0 1 1 1
1 0 1 1 1 0


0 0

输出例子:

7


分析:利用BFS求连通块

代码:

var
  a:array [1..101,1..101] of 0..1;
  f:array [1..101,1..101] of boolean;
  i,j,n,m,x,m1,n1,max:longint;
  ch:string;


procedure js(m1,n1:longint);
begin
  if (m1>m) or (n1>n) then exit;
  a[m1,n1]:=0;
  if (m1>1)and(a[m1-1,n1]<>0) then
  begin
    js(m1-1,n1);
  end;
  if (n1>1)and(a[m1,n1-1]<>0) then
  begin
    js(m1,n1-1);
  end;
  if (a[m1,n1+1]<>0) then
  begin
    js(m1,n1+1);
  end;
  if (a[m1+1,n1]<>0) then
  begin
    js(m1+1,n1);
  end;
  inc(x);
  exit;
end;


begin
  max:=0;
  x:=0;
  readln(m,n);
  for i:=1 to m do
  begin
    for j:=1 to n do
    begin
      read(a[i,j]);
    end;
    readln;
  end;
  for i:=1 to m do
  begin
    for j:=1 to n do
    begin
      if a[i,j]<>0 then js(i,j);
      if max<x then max:=x;
      x:=0;
    end;
  end;
  writeln(max);
end.


5.解救ice-cream

描写叙述 Description 
给你一张坐标图,s为Tina的初始位置。m为Ice-cream home的位置。‘.’为路面,Tina在上面,每单位时间能够移动一格;‘#’为草地,Tina在上面,每两单位时间能够移动一格(建议不要模仿—毕竟Tina还小);‘o’是障碍物,Tina不能在它上面行动。也就是说,Tina仅仅能在路面或草地上行走,必须绕过障碍物。并到达冰淇淋店。但是…………不保证到达时,冰淇淋还未融化,所以……就请聪明的你……选择最佳的方案啦…………假设。Tina到的时候,冰淇淋已经融化完了,那她但是会哭的。


输入格式 Input Format
依次输入冰淇淋的融化时间t(0<t<1000),坐标图的长x,宽y(5<=x,y<=25){太长打起来好累……},和整张坐标图。


输出格式 Output Format
推断依照最优方案能否够赶在冰淇淋融化之前到达冰淇淋店(注:当T=最优方案所用时间,则推断为未赶到),如赶到,输出所用时间;如未赶到。输出Tina的哭声——“55555”(不包含引號)。


例子输入 Sample Input

11
10
8
......s...
..........
#ooooooo.o
#.........
#.........
#.........
#.....m...
#.........

例子输出 Sample Output

10


时间限制 Time Limitation
  各个測试点1s

分析:利用BFS求加权单源最佳路径

借用王大牛代码:

program P1340;
type
        rec=record
                x,y:longint;
                di:longint;
                time:longint;
        end;
var
        s:array[1..100000,1..4] of longint;
        time:array[1..30,1..30] of longint;
        a:array[1..30,1..30] of char;
        sb1,sb2:char;
        b:array[1..30,1..30] of longint;
        q,open,closed,t,x,y,x0,y0,x1,y1,i,j,k,l,m:longint;
begin
        q:=maxlongint;
        assign(input,'haha.in');
        reset(input);
        readln(t);
        read(x,y);
        for j:=1 to y do
                begin
                read(sb1,sb2);
                 for i:=1 to x do
                        begin
                                read(a[i,j]);
                                if a[i,j]='.'then b[i,j]:=1
                                        else if a[i,j]='#'then b[i,j]:=2
                                                else if a[i,j]='o' then b[i,j]:=maxlongint
                                                        else if a[i,j]='s' then begin x0:=i;y0:=j; b[i,j]:=1;end
                                                        else if a[i,j]='m' then begin x1:=i;y1:=j; b[i,j]:=0;end;
                        end;
                 end;
        close(input);
        for j:=1 to y do
                for i:=1 to x do
                        time[i,j]:=maxlongint;
        closed:=0; open:=1;
        s[1,1]:=x0; s[1,2]:=y0; s[1,3]:=0; s[1,4]:=0;
        repeat
        repeat
                inc(closed);
                if time[s[closed,1],s[closed,2]]>s[closed,4] then begin
                time[s[closed,1],s[closed,2]]:=s[closed,4];
                if (s[closed,3]<>1)and(s[closed,1]<x)and(a[s[closed,1]+1,s[closed,2]]<>'o')then begin
                                                                inc(open);
                                                                s[open,1]:=s[closed,1]+1;
                                                                s[open,2]:=s[closed,2];
                                                                s[open,3]:=3;
                                                                s[open,4]:=s[closed,4]+b[s[closed,1],s[closed,2]];
                                                                end;
                                                                if a[s[open,1],s[open,2]]='m' then break;
                if (s[closed,3]<>3)and(s[closed,1]>1)and(a[s[closed,1]-1,s[closed,2]]<>'o') then begin
                                                                inc(open);
                                                                s[open,1]:=s[closed,1]-1;
                                                                s[open,2]:=s[closed,2];
                                                                s[open,3]:=1;
                                                                s[open,4]:=s[closed,4]+b[s[closed,1],s[closed,2]];
                                                                end;
                                                                if a[s[open,1],s[open,2]]='m' then break;
                if (s[closed,3]<>0)and(s[closed,2]>1)and(a[s[closed,1],s[closed,2]-1]<>'o') then begin
                                                                inc(open);
                                                                s[open,1]:=s[closed,1];
                                                                s[open,2]:=s[closed,2]-1;
                                                                 s[open,3]:=2;
                                                                s[open,4]:=s[closed,4]+b[s[closed,1],s[closed,2]];
                                                                end;
                                                                if a[s[open,1],s[open,2]]='m' then break;
                if (s[closed,3]<>2)and(s[closed,2]<y)and(a[s[closed,1],s[closed,2]+1]<>'o') then begin
                                                                inc(open);
                                                                s[open,1]:=s[closed,1];
                                                                s[open,2]:=s[closed,2]+1;
                                                                s[open,3]:=0;
                                                                s[open,4]:=s[closed,4]+b[s[closed,1],s[closed,2]];
                                                                end;
                                                                if a[s[open,1],s[open,2]]='m' then break;
                end;
        until (a[s[open,1],s[open,2]]='m')or(closed=open);
        if q>s[open,4] then q:=s[open,4];
        until (closed=open);
        if q>=t then write('55555')
        else
        write(q);
end.



原文地址:https://www.cnblogs.com/liguangsunls/p/7148826.html