博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

最短变换问题

Posted on 2010-10-20 11:07  桃子在路上  阅读(223)  评论(0编辑  收藏  举报

 已知字母A,B和一组字母变换规则(至多100个规则): A1->B1 A2->B2 规则的含义为:如果A=Ak,可以通过一次变换为Bk(1≤k ≤ 规则数) 求从A到B最少需要几次变换。
【输入文件】letter.in
第一行为两个字母,分别是初始字母和变换目标字母。 以下k行为变换规则(1 ≤ k ≤ 100),都是大写字母,两个字母间以空格间隔,直到文件结束。
【输出文件】letter.out
最小的变换次数。如果无法变换,则输入”No Answer!”

【样例数据】 

【输入】letter.in
A Z
A E
E F
F T
T Z
A C
C Z
【输出】letter.out
2

参考程序

{【算法分析】如果我们建一张有向图,把每一个字母看作结点,
那么变换AK->BK就是一条从AK到BK的权为1的有向边,
那么变换需要的步数就是起点到终点的最短路径长度。
可以应用经典的dijkstra算法}

program letter;
type
  path=record
    length:integer;
    pre:'A'..'Z';
  end;
var
  w:array['A'..'Z','A'..'Z'] of integer;
  dist:array['A'..'Z'] of path;
  s,t,x,y,u,i,j,ch:char;
procedure init;
 begin
  assign(input,'letter.in');
  reset(input);
  assign(output,'letter.out');
  rewrite(output);
  readln(s,ch,t);               {因为是字母,之间的空格必须略过}
  for x:='A' to 'Z' do
    for y:='A' to 'Z' do
       if x<>y
         then w[x,y]:=101       {最多100个规则,所以最大值101就够了}
         else w[x,y]:=0;
  while not eof(input) do
    begin
      readln(x,ch,y);
      w[x,y]:=1;
    end;
 end;
procedure dijkstra(v0:char);
var
  min:integer;
begin
  w[v0,v0]:=1;
  for i:='A' to 'Z' do
    begin
      dist[i].length:=w[v0,i];
      if dist[i].length<>101
         then dist[i].pre:=v0;
    end;
repeat
    min:=101;
    u:=' ';
    for i:='A' to 'Z' do
      if (w[i,i]=0) and (dist[i].length<min)
        then begin
               u:=i;
               min:=dist[i].length;
             end;
if u<>' '
       then begin
              w[u,u]:=1;
              for i:='A' to 'Z' do
                if (w[i,i]=0) and (dist[i].length>dist[u].length+w[u,i])
                   then begin
                          dist[i].length:=dist[u].length+w[u,i];
                          dist[i].pre:=u;
                        end;
            end;
  until u=' ';
end;
begin
  init;
  dijkstra(s);
  if dist[t].length<>101
    then write(dist[t].length)
    else write('No Answer!')
  close(input);
  close(output);
end.