回 帖 发 新 帖 刷新版面

主题:在一个瓶中装有80毫升化学溶剂,实验中需要精确地平分成两份,没有量具,只有两个杯子,其中一个杯子的容

在一个瓶中装有80毫升化学溶剂,实验中需要精确地平分成两份,没有量具,只有两个杯子,其中一个杯子的容量是50毫升,另一个是30毫升,试设计一个程序将化学溶剂对分成两个40毫升,并以最少步骤给出答案。
  分析:三个杯子水的初始状态为:80、0、0,生成新结点状态的方法为:将一个不空的杯子水倒入一个不满的杯中,且结点状态不重复,直到生成目标结点为止。
  算法步骤:
  ⒈数据库: 用数组d构成存放生成结点(杯子水状态)的队;数组p作为指向父结点的指针;t和s作为队头与队尾指针。
  ⒉结点的产生: 
  (1)将结点中不空的杯子水倒入一个不满的杯子中,生成新的结点并记下父结点位置;
  (2)判断新结点是否已生成过, 以避免死循环;
  (3)生成的结点若为目标结点,输出。
  ⒊搜索策略: 广度优先搜索。
  源程序如下:
program ex3;
type
 status= array [1..3] of integer;
const
 v: array [1..3] of integer =(80,50,30);
var
 d: array [1..200] of status;
 p: array [1..200] of integer;
 t,s,i,j: integer;
procedure draw(f: integer);{输出}
var
 m: array [1..20] of integer;
 i,j,k: integer;
begin
 j:=0;
 while f<>1 do begin
  inc(j);
  m[j]:=f;
  f:=p[f];
 end;
 writeln;
 writeln('Start: ',d[1,1]:3,d[1,2]:3,d[1,3]:3);
 for i:=j downto 1 do begin
  write('Step No.',j+1-i,': ');
  for k:=1 to 3 do write(d[m[i],k]:3);
  writeln;
 end;
 writeln('End.');
 halt;
end;
function exampass(w: integer): boolean;{新结点是否以前生成过}
var
 i: integer;
begin
 for i:=1 to w-1 do
  if (d[i,1]=d[w,1]) and (d[i,2]=d[w,2]) and (d[i,3]=d[w,3])
  then begin
   exampass:=false;
   exit;
  end;
 exampass:=true;
end;
function isobject(w: integer): boolean;{是否为目标结点}
begin
 if (d[w,1]=40) and (d[w,2]=40) then isobject:=true
 else isobject:=false;
end;
begin {生成新结点,将一个不空的杯子水倒入一个不满的杯子中}
 d[1,1]:=80; d[1,2]:=0; d[1,3]:=0;
 p[1]:=0;
 t:=1; s:=2;
 repeat
  for i:=1 to 3 do
   if d[t,i]<>0 then
    for j:=1 to 3 do
     if (i<>j) and (d[t,j]<>v[j]) then begin
      d[s]:=d[t];
      d[s,j]:=d[s,j]+d[s,i];
      d[s,i]:=0;
      if d[s,j]>v[j] then begin
       d[s,i]:=d[s,j]-v[j];
       d[s,j]:=v[j];
      end;
      p[s]:=t;
      if exampass(s) then begin
       if isobject(s) then draw(s);
       inc(s);
      end;
     end;
   inc(t);
 until t>=s;
 writeln('NoWay');
end.

回复列表 (共1个回复)

沙发


你别耍酷了,谁不知你才5年级,别到处乱找难题

我来回复

您尚未登录,请登录后再回复。点此登录或注册